Здесь Р1 — указатель на динамическую величину целого типа; P2 — указатель на динамическую величину символьного типа; PM — указатель на динамический массив, тип которого задан в разделе Type.
Во время компиляции память выделяется только под статические величины. Указатели — это статические величины, поэтому они требуют описания.
Каким же образом происходит выделение памяти под динамическую величину? Память под динамическую величину, связанную с указателем, выделяется в результате выполнения стандартной процедуры NEW. Формат обращения к этой процедуре выглядит так:
NEW(<указатель>);
Считается, что после выполнения этого оператора создана динамическая величина, имя которой имеет следующий вид:
<имя динамической величины>::=<указатель>^.
Пусть в программе, в которой имеется приведенное выше описание, присутствуют операторы
NEW(Pl); NEW(P2); NEW(PM);
После их выполнения в динамической памяти оказывается выделенным место под три величины (две скалярные и один массив), которые имеют идентификаторы
P1^, Р2^, РМ^
Например, обозначение P1^ можно расшифровать так: динамическая переменная, на которую ссылается указатель Р1.
На схеме, представленной на рис. 39, показана связь между динамическими величинами и их указателями.
Дальнейшая работа с динамическими переменными происходит точно так же, как со статическими переменными соответствующих типов. Им можно присваивать значения, их можно использовать в качестве операндов в выражениях, параметров подпрограмм и т.п. Например, если переменной Р1^ нужно присвоить значение 25, переменной P2^ присвоить значение символа 'W', a массив PM^ заполнить по порядку целыми числами от 1 до 100, то это делается так:
Р1^:=25;
Р2^: ='W';
For I:=l То 100 Do PM^ [I]:=I;
Кроме процедуры NEW значение указателя может определяться оператором присваивания:
<указатель>:=<ссылочное выражение>;
В качестве ссылочного выражения можно использовать:
• указатель;
• ссылочную функцию (т. е. функцию, значением которой является указатель);
• константу Nil.
Nil — это зарезервированная константа, обозначающая пустую ссылку, т. е. ссылку, которая ни на что не указывает. При присваивании базовые типы указателя и ссылочного выражения должны быть одинаковыми. Константу Nil можно присваивать указателю с любым базовым типом.
До присваивания значения ссылочной переменной (с помощью оператора присваивания или процедуры NEW) она является неопределенной.
Ввод и вывод указателей не допускается. Рассмотрим пример. Пусть в программе описаны следующие указатели:
Var D,P:^Integer;
К: ^Boolean;
Тогда допустимыми являются операторы присваивания
D:=P; K:=Nil;
поскольку соблюдается принцип соответствия типов. Оператор K:=D ошибочен, так как базовые типы у правой и левой части разные.
Если динамическая величина теряет свой указатель, то она становится «мусором». В программировании под этим словом понимают информацию, которая занимает память, но уже не нужна.
Представьте себе, что в программе, в которой присутствуют описанные выше указатели, в разделе операторов записано следующее:
NEW(D); NEW(P) ;
{Выделено место в динамической памяти под
две целые переменные. Указатели получили
соответствующие значения)
D^:=3; Р^:=5;
{Динамическим переменным присвоены
значения}
P:=D;
{Указатели Р и D стали ссылаться на одну и
ту же величину, равную 3}
WriteLn(P^,D^); {Дважды напечатается число 3}
Таким образом, динамическая величина, равная 5, потеряла свой указатель и стала недоступной. Однако место в памяти она занимает. Это и есть пример возникновения «мусора». На схеме, представленной на рис. 40, показано, что произошло в результате выполнения оператора Р:=D.
В Паскале имеется стандартная процедура, позволяющая освобождать память от данных, потребность в которых отпала. Ее формат:
DISPOSE(<указатель>);
Например, если динамическая переменная P^ больше не нужна, то оператор
DISPOSE(Р)
удалит ее из памяти. После этого значение указателя Р становится неопределенным. Особенно существенным становится эффект экономии памяти при удалении больших массивов.