ĆWICZENIE 4 Wskaźniki
Celem ćwiczenia jest zapoznanie z podstawowymi operacjami na wskaźnikach.
I. PRZEBIEG ĆWICZENIA
1. Wprowadzić program ilustrujący podstawowe operacje wskaźnikach:
program Przyklad1;
var x : byte;
ptrX : ^byte; {ptrX jest wskaźnikiem do zmiennej typu
Byte=ptrX przechowuje adres (dowolnej) zmiennej typu Byte}
begin x:=3;
ptrX:=@x; {ptrX jest równe Adresowi zmiennej x}
writeln(x); {Wynik: 3}
writeln(ptrX^); {Wynik: 3. ptrX^ oznacza: Wykonaj operację na tej zmiennej, na którą wskazuje ptrX}
ptrX^:=86; {Ponieważ ptrX wskazuje na x, więc (ptrX^) i x to dokładnie to samo.}
writeln(x); {Wynik: 86}
writeln(ptrx^); {Wynik: 86}
end.
2. Wprowadzić inny program ilustrujący podstawowe operacje wskaźnikach:
program Przyklad2;
var x : integer;
ptrX : ^integer; {Wskaźniki działają dla dowolnego typu (możliwy jest nawet wskaźnik do wskaźnika! W szczególności działają dla typu rekordowego.)
ptrY : ^integer;
begin x:=3;
ptrX:=@x;
ptrY:=@x;
ptrY^:=2; {Tutaj ptrY^ przyjmie wartość 2. Ponieważ ptrY=@x, więc x również przyjmie wartość 2. Ponieważ ptrX^=x, więc ptrX^ również będzie równało się dwa!}
writeln(x); {Wynik: 2}
writeln(ptrX^); {Wynik: 2}
writeln(ptrY^); {Wynik: 2}
end.
3. Wprowadzić program ilustrujący przydział i zwalnianie pamięci dla prostych zmiennych:
program Przyklad3;
var ptrX : ^byte; {ptrX jest wskaźnikiem do zmiennej typu Byte}
begin
new(ptrX); {Utworzenie nowej zmiennej typu Byte i przypisanie adresu do niej wskaźnikowi ptrX}
ptrX^:=4; {Na tej nowoutworzonej zmiennej można wykonywać takie same operacje, jak na każdej innej zmiennej typu Byte}
writeln(ptrX^);
dispose(ptrX);
ptrX:=nil; {nil oznacza „pusty wskaźnik”. Stosowany jest dla uniknięcia błędów w programie.
Umowa jest taka, że wskaźnik wskazujący na nil nie wskazuje na nic.}
end.
4. Wprowadzić program ilustrujący podstawowe operacje na wskaźnikach do rekordów:
program Przyklad4;
type TRekord = record x : byte;
y : integer;
end;
TRekordPtr = ^TRekord;
var ptrRek : TRekordPtr;
rek : TRekord;
begin rek.X:=2;
rek.Y:=5;
ptrRek:=@rek; { ptrRek wskazuje na CAŁY rekord}
writeln(ptrRek^.X); {Dlatego trzeba użyć operatora „.“ (kropka) do odwołania się do poszczególnych pól – tak, jak zwykle. Skoro ptrRek^ jest rekordem, to ptrRek^.x jest polem x tego rekordu.
Oczywiście ptrRek.x (bez daszka „^”) jest błędne, gdyż ptrRek jest WSKAŹNIKIEM do rekordu, a nie rekordem.}
writeln(ptrRek^.Y);
end.
5. Wprowadzić program ilustrujący dynamiczne tworzenie rekordów:
program Przyklad5;
type TRekord = record x : byte;
y : string;
end;
TRekordPtr = ^TRekord;
var ptrRek : TRekordPtr;
begin
new(ptrRek); {Utworzenie zmiennej ptrRek^. Od teraz można pisać ptrRek^}
ptrRek^.X:=34;
ptrRek^.Y:='Ala ma kota!';
writeln(ptrRek^.Y); {Wynik: Ala ma kota!}
dispose(ptrRek); {PAMIĘĆ DLA ptrRek ZOSTAŁA ZWOLNIONA. ZMIENNA PtrRek^ (z daszkiem na końcu) OD TEJ CHWILI NIE ISTNIEJE!}
{UWAGA: JAK KTOŚ MI W TYM MIEJSCU NAPISZE:
WRITELN(ptrRek^.Y) TO POSTAWIĘ MU DWÓJĘ NA WEJŚCIÓWCE!
Pamięć dla ptrRek została zwolniona, więc BEZWZGLĘDNIE, CAŁKOWICIE, ABSOLUTNIE ZABRONIONE JEST ODWOŁYWANIE SIĘ DO ZMIENNEJ, KTÓREJ PAMIĘĆ ZOSTAŁA ZWOLNIONA!!!
PtrRek^ NIE WSKAZUJE NA ŻADNĄ SENSOWNĄ ZMIENNĄ (PRZECIEŻ PO TO WYKONANO dispose(ptrRek)). Oczywiście nadal możliwe są operacje na wskaźniku ptrRek – jest to przecież zmienna statyczna (deklarowana przez var). Jeśli ptrRek^ nie jest adresem zmiennej, obowiązuje CAŁKOWITY ZAKAZ odwoływania się do niej. }
end. {koniec programu}
6. Wprowadzić program ilustrujący dynamiczne tworzenie rekordów (Działa identycznie, jak przykład 5, różnica jest jedynie w deklaracji typów):
program Przyklad6;
type
TRekordPtr = ^TRekord; {Tak też jest dobrze! Można deklarować wskaźnik do typu, który zostanie zadeklarowany poniżej. }
TRekord = record x : byte;
y : string;
end;
var ptrRek : TRekordPtr;
begin
new(ptrRek);
ptrRek^.X:=34;
ptrRek^.Y:='Ala ma kota!';
writeln(ptrRek^.Y);
dispose(ptrRek);
end.
7. Wprowadzić program ilustrujący dynamiczne tworzenie rekordów:
program Przyklad7;
type
TRekordPtr = ^TRekord;
TStrPtr = ^string;
TRekord = record x : byte;
ptrStr : TStrPtr;
end;
var ptrRek : TRekordPtr;
begin
new(ptrRek);
new(ptrRek^.ptrStr);
ptrRek^.ptrStr^:='Ala ma kota!';
writeln(ptrRek^.ptrStr^);
dispose(ptrRek^.ptrStr);
ptrRek^.ptrStr:=nil;
dispose(ptrRek);
ptrRek:=nil;
end.