Deklarálása: azonosító: ^alaptípus Pl. Var p1, p2: ^real;
A mutató egy memóriacímet (4 bájtos: szegmens, ofszet) tartalmaz, egy alaptípusú változóra mutat. A mutatóhoz futás közben rendelhetünk memóriacímet és így tárterületet (dinamikus adattárolás).
A New eljárás a heap memóriában foglalterületet a mutatott változó számára, a Dispose eljárás pedig felszabadítja a lefoglalt területet. Így lehetõvé válik, hogy egy nagy helyfoglalású adatstruktúra számára csak akkor kössünk le memóriát, amikor használjuk a változót. Nézzünk erre egy példát:
type TTomb = array[1..1000]of real;
var t: TTomb; {A rendszer már a program idításakor lefoglal 6000 bájtot az adatszegmensben}
pt: ^TTomb;{A rendszer a program idításakor csak 4 bájtot foglal le a mutató számára}
begin
...
New(pt); {A heap-ben létrejön a mutatott változó}
... {Használhatom a pt által mutatott változót (pt^)}
Dispose(pt) {A terület felszabadul a heap-ben}
end.
A mutatót ráirányíthatjuk egy az alaptípusával megegyezõ típusú változóra a @ operátorral vagy az Addr függvénnyel. Pl. pt := @t; vagy pt := Addr(t).
A Ptr függvénnyel a mutatónak egy tetszõleges memóriacímet adhatunk értékül.
A negyedik lehetõség arra, hogy egy mutatóhoz egy memóriacímet rendeljünk: értékadó utasítás egy vele azonos alaptípusú mutatóval.
Hivatkozás a mutatott változóra: mutató-azonosító^ (pl.: pt^[12] := 1)
Mutató típusú konstans: Nil.
A Nil nem mutat sehová. (Pl. láncolt lista végének a jelzésére használhatjuk).
Mûveletek: Címe: @ Egyenlõség vizsgálat: =, <>
További szabványos eljárások, függvények:
Eljárások: Mark, Release Függvények: MaxAvail, MemAvail, Ofs, Seg
Láncolt listák: A különbözõ típusú láncolt listák nagyon fontos adatszerkezetek a számítástechnikában. Az egyes adatelemek (rekordok) közötti csatolást mutatókkal valósíthatjuk meg, így a rekordnak van egy mutató típusú mezõje, melynek alaptípusa maga a rekord. Az alábbi példában figyeljük meg, hogy a mutató típus deklarálásánál olyan azonosítót használunk, amely a programunkban csak késõbb szerepel. (A Pascal ebben az egy esetben engedi ezt meg.)
type Mutato = ^Adatelem;
Adatelem = record
Adat: real;
Kovetkezo: Mutato;
end;
var Elso, Uj, Aktualis: Mutato;
Példák: 1. Fûzzük fel láncolt listára a billentyûzetrõl beolvasott számokat. Írassuk ki a listát!
Megoldás: Láncolt lista - példaprogramok
1.
program Lista1;
uses Crt;
type TMutato = ^TAdatElem;
TAdatElem = record
Adat: integer;
Kovetkezo: TMutato;
end;
var Elso, Aktualis, Uj: TMutato;
a: integer;
begin
ClrScr;
ReadLn(a);
Elso := nil;
while a <> 0 do
begin
New(Uj); {Az Uj mutatóhoz memóriaterület rendelése}
Uj^.Adat := a;
Uj^.Kovetkezo := nil;
if Elso = nil then
Elso:=uj {Elsõ rekord, az Elso mutat az Uj-ra}
else
Aktualis^.Kovetkezo := Uj; {Az Aktualis-hoz csatoljuk az Uj-at}
Aktualis := Uj; {Az Aktualis léptetése}
ReadLn(a)
end;
{A lista megjelenítése}
WriteLn;
Aktualis := Elso;
while Aktualis <> nil do
begin
WriteLn(Aktualis^.Adat);
Aktualis := Aktualis^.Kovetkezo
end;
ReadKey
end.
2. Fûzzük fel rendezett láncolt listára a billentyûzetrõl beolvasott számokat. Írassuk ki a listát!
Megoldás
program Lista2;
uses Crt;
type TMutato = ^TAdatElem;
TAdatElem = record
Adat: integer;
Kovetkezo: TMutato;
end;
var Elso, Aktualis, Uj, Elozo: TMutato;
Szam: integer;
begin
ClrScr;
Elso := nil;
ReadLn(Szam);
while Szam <> 0 do
begin
New(Uj);
Uj^.Adat := Szam;
Uj^.Kovetkezo := nil;
{Az Uj rekord helyének a megkeresése a rendezett listában}
Aktualis := Elso;
while (Aktualis <> nil) and (Aktualis^.Adat < Uj^.Adat) do
begin
Elozo := Aktualis;
Aktualis := Aktualis^.Kovetkezo;
end;
{Az Uj rekord beillesztése a listába}
if Aktualis = Elso then {Az Elso elem lesz}
Elso := Uj
else {Az Elozo mögé, az Aktualis elé}
Elozo^.Kovetkezo := Uj;
Uj^.Kovetkezo := Aktualis;
ReadLn(Szam)
end;
{A lista megjelenítése}
WriteLn;
Aktualis := Elso;
while Aktualis<>nil do
begin
WriteLn(Aktualis^.Adat);
Aktualis := Aktualis^.Kovetkezo;
end;
readkey
end.
Deklarálása: POINTER
Egy négy bájtos memóriacímet tartalmaz. A mutatott változónak nincs típusa. A típusnélküli mûveleteknél használjuk (pl. adatmozgatás).
A GetMem eljárással foglalhatunk le egy megadott méretû területet a heap-ben a mutatónk számára. Ha a memóriaterületre már nincs szükségünk a FreeMem eljárással azt felszabadíthatjuk.
A mutatót ráirányíthatjuk akármilyen címre vagy változóra a @ operátorral vagy az Addr függvénnyel. Pl. p := @tomb1; vagy p := Addr(tomb1).
A Ptr függvénnyel a mutatónak egy tetszõleges memóriacímet adhatunk értékül.
Egy mutató értékadó utasítással egy másik mutató címét is felveheti.
A mutatott változóhoz rendelhetünk típust: típus(mutató-azonosító^).
Hivatkozás a mutatott változóra: mutató-azonosító^
Mutató típusú konstans: Nil.
Mûveletek:
Címe: @
Egyenlõség vizsgálat: =, <>
További szabványos függvények: MaxAvail, MemAvail, Ofs, Seg
Példa: 1. Mentsünk el egy garfikát egy típus nélküli állományba, majd olvassuk vissza!
Megoldás: Típusnélküli mutató - példaprogram
program KepMent;
uses Crt, Graph;
var f: file; {A típusnélküli állomány, amelybe mentjük a képet}
kep: pointer; {A kép memóriába való elmentéséhez szükséges mutató}
d, m: integer;
meret: word;
grd, grm, a, b, c, px, py, py1, i: integer;
x, y: real;
begin
{Grafika kirajzolása (két függvény ábrázolása)}
d := detect;
InitGraph(d, m, 'c:\bp\bgi');
a := 1;
b := -2;
c := -3;
for i := 0 to 640 do PutPixel(i,240,14);
for i := 0 to 64 do begin PutPixel(10*i,241,14); PutPixel(10*i,239,14) end;
for i := 0 to 480 do PutPixel(320,i,14);
for i := 0 to 48 do begin PutPixel(319,10*i,14); PutPixel(321,10*i,14) end;
for i := -320 to 320 do
begin
x := i/10;
y := 5*Sin(x/4);
px := Round(10*x + 320);
py := Round(-10*y + 240);
py1 := Round(-10*x + 240);
if (py < 480) and (py > 0) then PutPixel(px,py,15);
if (py1 < 480) and (py1 > 0) then PutPixel(px,py1,15)
end;
Assign(f, 'kepment.dat');
Rewrite(f);
{A képet négy részletben tudjuk elmenteni}
meret := ImageSize(0, 0, 319, 239); {A negyedkép mérete}
GetMem(kep, meret); {Helyfoglalás a típusnélküli mutatónak a heap-ben}
GetImage(0, 0, 319, 239, kep^); {Negyedkép elmentése a mutatott területre}
BlockWrite(f, kep^, meret div 128); {A memóriaterület elmentése a fájlba}
GetImage(320, 0, 639, 239, kep^);
BlockWrite(f, kep^, meret div 128);
GetImage(0, 240, 319, 479, kep^);
BlockWrite(f, kep^, meret div 128);
GetImage(320, 240, 639, 479, kep^);
BlockWrite(f, kep^, meret div 128);
FreeMem(kep, meret); {A memóriaterület felszabadítása}
{A kép visszaolvasása}
ReadKey;
ClearDevice;
ReadKey;
Reset(f);
GetMem(kep, meret); {Helyfoglalás a típusnélküli mutatónak a heap-ben}
BlockRead(f, kep^, meret div 128); {Adatmozgatás a fájlból a lefoglalt memóriaterületre}
PutImage(0, 0, kep^, copyput); {A negyedkép kirajzolása}
BlockRead(f, kep^, meret div 128);
PutImage(320, 0, kep^, copyput);
BlockRead(f, kep^, meret div 128);
PutImage(0, 240, kep^, copyput);
BlockRead(f, kep^, meret div 128);
PutImage(320, 240, kep^, copyput);
FreeMem(kep, meret); {A memóriaterület felszabadítása}
ReadKey;
end.