Zpět na seznam článků     Číst komentáře (0)     Verze pro tisk

Pascal pro začátečníky 12 - Dynamické proměnné

Autor: Kub@z   
1.5.2004

V této lekci se dozvíte, co jsou to dynamické proměnné a jak se s nimi pracuje...


Ano, dostáváme se k tomu, co jsem sliboval v úvodu - dynamické proměnné. Jistě si říkáte: "Co to asi ta dynamická proměnná je?" Dosud jsme používali pouze statické proměnné. To znamená, že jsme si je nadeklarovali a dále v programu jsme je používali. Ale co když nastane situace, kdy nebudete vědět, kolik proměnných budete potřebovat a budete nuceni je vytvořit během programu? Tak to už si se statickými proměnnými nevystačíte. Pascal obsahuje datový typ "pointer". Je to ukazatel na místo v paměti, kde je uložena hodnota. Toho, aby překladač poznal, že deklarujeme ukazatel a ne proměnnou určitého typu, docílíme znakem "^" (pro zrychlení - tento znak napíšete pomocí ALT + 94). Příklad:

type ukazatel = ^integer;

Tím jsme si vytvořili ukazatel na typ integer. S tímto ukazatelem nemůžeme pracovat tak, že do něj přiřadíme hodnotu (protože tím bychom vlastně řekli ukazateli, na jaké místo v paměti má ukazovat), ale musíme přiřadit hodnotu do paměti, kam ukazatel ukazuje. Tuto paměť musíme nejdříve vyhradit procedurou "new":

type ukint = ^integer;
var prom: ukint; (* proměnná je ukazatel (možno zapsat jako "prom: ^integer") *)
begin
new(prom);       (* získáme paměť *)
prom^ := 50; (* do místa v paměti, kam ukazuje "prom", zapíšeme hodnotu *)
writeln(prom^); (* přesvědčíme se, že se hodnota opravdu uložila *)
end.

Pokud chceme, aby ukazatel ukazoval "nikam", provedeme to klíčovým slovem "nil" (v našem případě by to bylo "prom := nil" - bez "^"!). Tím jsme ale stále nedocílili toho, abychom mohli vytvořit za běhu programu neomezený počet proměnných. To co jsme udělali je vlastně jen složitější práce s normální proměnnou. Většího počtu dosáhneme takto:

type pint = ^int; (* ukazatel na náš záznam *)
    int = record
          hodnota: integer;
          dalsi: pint;
          end;
var prvni, ak: pint;
   pom: integer;
begin
new(ak);          (* vyhradíme si paměť *)
prvni := ak;      (* prvni ukazuje na první položku *)
repeat
 readln(pom);     (* uživatel zadá hodnotu *)
 ak^.hodnota := pom;
 new(ak^.dalsi);  (* vytvoříme další položku *)
 ak := ak^.dalsi; (* "ak" ukazuje na další položku *)
 ak^.dalsi := nil; (* nechceme, aby další položka měla nějakou hodnotu *)
until pom = 0;      (* zadáváme čísla, dokud není zadána nula *)

(* nyní všechny položky vypíšeme *)
ak := prvni;  (* "ak" zase ukazuje na první položku *)

while ak^.dalsi <> nil do begin (* dokud existuje další položka *)
 writeln(ak^.hodnota);          (* vypíšeme její hodnotu *)
 ak := ak^.dalsi;
end;

end.

Teď mam takový neblahý dojem, že to asi nechápete. Jestli to tak opravdu je, zkuste si prostudovat ten příklad s jednou proměnnou a až ho pochopíte, projděte si řádek po řádku v dalším příkladu s "neomezeným" počtem proměnných. Snad to časem pochopíte. Jdeme dál. S ukazateli souvisí i funkce "ptr(segment, offset)", díky které můžete zařídit, aby ukazatel ukazoval na určité místo v paměti. Jenomže to zase zabíháme moc hluboko do znalosti hardwaru počítače, proto tady uvedu pouze příklad:

var m: ^byte;
begin
m := Ptr($40, $49); (* adresa videomódu v paměti *)
writeln('Videomod: ',m^);
end.

S tím souvisí i funkce "addr(x)", jejíž parametr tvoří jméno proměnné. "Addr" vrací adresu paměti, ve které je proměnná uložena:

var p: pointer;
   pom: string;
begin
pom := 'Ahoj lidi, jak se mate?'; (* zadáme text *)
p := addr(pom); (* "p" teď ukazuje na adresu "pom" v paměti *)
writeln(string(p^)); (* vypíšeme, co se v této paměti vyskytuje, abychom se *)
                  (* přesvědčili, že "p" ukazuje opravdu na adresu "pom" *)
end.

Proměnnou "p" musíme nejprve přetypovat na string, protože samotné "p" je neznámého typu. To bychom samozřejmě udělat nemuseli, pokud by "p" nebylo typu "pointer" ale typu "^string", neboli "pointer to string" (tak se to zapsat samozřejmě nedá :) S tím souvisí i funkce "ofs(x)" a "seg(x)", které vrací offset, resp. segment proměnné. K další práci s přidělením paměti pointeru slouží procedury "getmem(pointer, velikost)" a "freemem(pointer, velikost). Maximální velikost přidělené paměti je 65528 bytů. Příklad:

var p: pointer;
begin
getmem(p, 20000); (* právě máme k dispozici 20 KB paměti *)
freemem(p, 20000); (* ale my je nevyužijeme a zase je z paměti uvolníme *)
end.

To je zatím o dynamických proměnných vše

Líbil se Vám článek?
Budeme potěšeni, pokud vás zaujme také reklamní nabídka

Social Bookmarking

     





Hodnocení/Hlasovalo: 1.88/25

1  2  3  4  5    
(známkování jako ve škole)