Типизированным называется указатель, который указывает (ссылается) на данные определенного типа. Для его объявления используется символ ^, который размещается перед соответствующим типом данных. Например:
Type mas = array[1..100] of real;
Var p1: ^integer;
p2: ^mas;
В этом случае p1 – это ссылка (указатель) на целое число, p2 – ссылка на массив из 100 вещественных чисел. Для того, чтобы обратиться к данным по этим адресам, необходимо указать: p1^, p2^. То есть, p1 – это адрес, а p1^ - то, что по этому адресу находится.
Для выделения участка динамически распределяемой памяти (кучи) в целях размещения там необходимых данных используется стандартная процедура
New (p);, где p – указатель.
После выполнения такой команды будет выделен блок памяти необходимого размера (для размещения тех данных, на которые ссылается указатель p), а сам указатель p приобретет значение адреса этого выделенного участка памяти. Например, после выполнения команд:
New (p1);
New (p2);
будет выделено два непрерывных участка кучи, первый размером 2 байта (т.к. целое число занимает 2 байта оперативной памяти), второй – 400 байтов (100 * 4 байта для каждого из 100 вещественный чисел).
|
|
После выполнения этих команд указатели p1 и p2 приобрели конкретные значения. Поэтому по адресам, на которые они указывают, можно размещать конкретные значения соответствующего типа. Например,
p1^:= 52;
p2^[1]:= 8;
Если в момент выполнения процедуры New в куче не окажется непрерывного участка памяти требуемого размера, то программа аварийно завершится с сообщением «Out of Memory». Для контроля размера доступного участка в динамически распределяемой памяти (куче) можно использовать функцию MaxAvail, которая возвращает размер максимального непрерывного участка кучи в текущий момент времени.
Для освобождения динамической памяти используется процедура
Dispose (p);, где p – указатель.
Например:
Dispose (p1);
Dispose (p2);
После выполнения такой команды память, ранее связанная с указателем, возвращается в кучу (и может быть вновь использована уже для хранения других данных). Однако значение самого указателя не меняется, т.е. в нем остается адрес «несуществующего» (уже отданного обратно в кучу) блока памяти. Поэтому обращение к указателю после выполнения команды Dispose может привести к ошибке.
В паскале существует константа Nil – пустой указатель. Значение Nil может быть присвоено любому указателю, например:
p2:= nil;
Однако выполнение такого присваивания до вызова процедуры
Dispose (p2) к тому, что указатель p2 не будет ссылаться ни на какой участок динамической памяти, а данные в памяти останутся, т.е. этот участок не будет возвращен в кучу. Это плохо по той причине, что при выполнении серии таких команд значительная часть динамической памяти будет считаться занятой, но использоваться не будет.
Константа Nil необходима при работе с динамическими структурами данных, что будет рассмотрено ниже.