Niepewność bywa czasem gorsza niż brak uzbrojonej straży.

w:=NIL; - przypisanie jej wartości innej zmiennej tego samego typu wskaźnikowego, np. v:=w; - wywołanie procedury standardowej NEW ze zmienną w lub v jako parametrem aktualnym, np. NEW (w). W dwóch pierwszych przypadkach instrukcje przypisania nie wymagają ko- mentarza. Wykonanie instrukcji NEW (w) powoduje zarezerwowanie pamięci na zapamiętanie wartości typu całkowitego i nadanie zmiennej w wartości, która jest wskaźnikiem do tego obszaru. Obszar ten należy do zmiennej dynamicznej, która jest dostępna przez identyfikator w" i traktowana jak każda inna zmienna typu INTEGER. Po wykonaniu instrukcji NEW (w) wartość zmiennej w" jest nieo- kreślona. Można nadać jej wartość, na przykład wykonując instrukcję: w":=25; 148 4. Elementy programowania w języku Pascal Wzajemne powiązania między opisanymi powyżej pojęciami są zilustrowanej na rysunku 4.2. NEW(w) w*:=25 w-------- 25 Rys. 4.2. Wskaźnik i zmienna dynamiczna Zauważmy, że ponowne wykonanie instrukcji NEW (w) powołuje nową zmien- ną dynamiczną w", a zatem tracimy przez to dostęp do wartości poprzednio wskazywanej przez wskaźnik w. Oszczędne gospodarowanie pamięcią zajmowaną przez zmienne dynamiczne jest możliwe dzięki istnieniu procedury standardo- wej DISPOSE. Wykonanie instrukcji DISPOSE(w) powoduje, że wartość zmiennej w staje się nieokreślona, a obszar pamięci zajmowany przez zmienną w" zostaje zwolniony i może być wykorzystany w innym celu. Praktyczny sens stosowania typów wskaźnikowych uwidacznia się w sytuacji, gdy typ wskazywany jest złożonym typem strukturalnym (np. tablicą lub rekor- dem) i zadeklarowanie zmiennej tego typu pociąga za sobą rezerwację znacznego obszaru pamięci, a istnieją przesłanki, że pamięć ta nie będzie w pełni wykorzy- stywana podczas działania programu. Na przykład, zdefiniujmy typy danych: TYPE DuzaTablica=ARRAY [1..5000] OF REAL; Wskazuj =~DuzaTablica; Wówczas zadeklarowanie zmiennej Tablica: VAR Tablica:Wskazuj; oznacza, że pamięć potrzebna do zapamiętania tablicy złożonej z 5000 liczb typu REAL zostanie przydzielona dopiero wtedy, gdy zmienna ta wystąpi jako parametr aktualny w procedurze NEW. Jeśli nie możemy przewidzieć, jak duże będą nasze dane, to musimy zagwa- rantować, że przydział pamięci dla kolejnego elementu będzie następował wraz z jego pojawieniem się. Tworzenie zmiennych dynamicznych jest właśnie takim postępowaniem. Zmienne dynamiczne wykorzystuje się do tworzenia list. Elementami listy są I rekordy połączone ze sobą za pomocą wskaźników. Uzyskujemy to definiując typ i 4.5. Dynamiczne struktury danych 149 wskaźnikowy, który wskazuje rekordy. Rekordy te mają pole typu wskaźnikowego i w tym polu umieszczamy wskaźnik do następnego rekordu lub wartość NIL, gdy brak jest następnego elementu. Zaproponujemy teraz definicje typów dla przykładu omówionego w poprze- dnim punkcie, które pozwolą utworzyć dziennik jako listę uczniów, w miejsce tablicy. W dalszych rozważaniach zachowamy takie same nazwy dla typów oraz zmiennych oznaczających te same wielkości. Dla ułatwienia uprościmy budowę rekordu gromadzącego informacje o uczniu i pozostawimy tylko pola Imię i Nazw. Przykład 4.21. Definicje typów danych dla listy uczniów. TYPE DziennikLekcyjny=~Uczen; Uczeń =REC0RD Imię,NazwrSTRING[15] ; Wsk :DziennikLekcyjny END; m Powyższa definicja zawiera wyjątek w języku Pascal, gdyż nazwa typu rekor- dowego Uczeń jest użyta w tekście programu wcześniej, niż została opisana. Taka sytuacja jest dopuszczalna tylko w definicji typu wskaźnikowego. Dla tak zdefiniowanego typu wskaźnikowego lista uczniów jest reprezentowana przez zmienną Dziennik VAR Dziennik:DziennikLekcyjny; w następujący sposób: - jeśli lista jest pusta, to zmiennej Dziennik nadajemy wartość NIL; - jeśli lista jest niepusta, to wartością zmiennej Dziennik jest wskaźnik do pierwszego elementu listy. Wskaźniki do następnych elementów są umieszczane w polach Wsk kolejnych rekordów. W ostatnim elemencie listy polu Wsk nadajemy wartość NIL, aby u- łatwić rozpoznanie końca listy. Struktura listy jest zilustrowana na rysunku 4.3. Dziennik - Imię Nazw Wsk NIL Rys. 4.3. Struktura listy zbudowanej za pomocą wskaźników 150 4. Elementy programowania w języku Pascal Napiszemy teraz program, który korzystając z nowych typów danych zdefinio- wanych w przykładzie 4.21, będzie czytał imiona i nazwiska uczniów z klawiatury