Ссылочные типы и указатели.

Ссылочные или указательные типы занимают промежуточное положение между скалярными и составными типами: с одной стороны, значения ссылочных типов являются атомарными (неразделимыми), с другой стороны, эти типы определяются через другие (в том числе и ссылочные) типы.

Любой ссылочный тип определяет множество значений, которые являются указателями на значение некоторого определенного типа.

Type

P = ^integer;

Var

P1, p2 : p;

OneMan : ^Person;

Значение переменной OneMan ссылается (указывает) на некоторое значение типа Person.

Описание ссылочных типов - единственное исключение из общего правила, согласно которому все идентификаторы должны быть описаны перед использованием.

Type

PtrType = ^BaseType;

BaseType = record

X, y :real;

End;

Рисунок 15.1 - Ссылочный тип

Реально значения ссылочных типов содержат адреса расположения в памяти конкретных значений базового типа. Чтобы присвоить переменной ссылочного типа некоторое значение, необходимо воспользоваться унарной операцией взятия указателя, которая строится из знака этой операции - символа '@' и одного операнда - переменной любого типа.

Var

I : integer;

То применение этой операции к переменной i : @i дает в качестве результата значение типа 'указатель на целое':

P1 :=@i;

Правомочен, т. к. в обеих его частях стоят конструкции одного и того же типа. В результате такого присваивания p1 получит в качестве своего нового значения указатель на переменную i (или адрес переменной i).

Операция взятия указателя допустима для любых переменных в том числе для элементов массива, полей записей и т. д.

Над значениями ссылочных типов допускаются две операции сравнения на равенство и неравенство; эти операции проверяют, ссылаются ли два указателя на одно и то же место в памяти.

S := p1 = p2;

If p1<>nil then …

Nil - служебное слово, обозначает, что указатель ссылается на место в адресном пространстве, в котором заведомо не может быть размещена никакая переменная.

P1 := @i;

Эта схема показывает, что для доступа к переменной i имеются две возможности: использовать для доступа идентификатор i, вторая - воспользоваться адресом этой переменной, который содержится в p1. Первый путь очевиден:

I: = i+2;

Для реализации второго, косвенного доступа к переменной через указатель (ссылку) на ней используется конструкция, называемая разыменованием. Общее правило: для того, чтобы по указателю на переменную получить доступ к самой этой переменной, необходимо после указателя поставить знак '^'.

P1^ - переменная, на которую ссылается p1.

P1^ :=P1^+2;

Разыменование считается не корректным, если ссылочная переменная имеет значение nil. В этом случае не существует переменной, на которую ссылается указатель.

P1:=nil

P1^ :=2 - является недопустимым.

До сих пор мы имели дело с переменными, которые размещаются в памяти согласно вполне определенным правилам. Для локальных переменных, описанных подпрограмме, память отводится при вызове подпрограммы: при выходе из нее эта память освобождается, а сами переменные прекращают существование. Глобальным переменным программы, память отводится в начале ее выполнения : эти переменные существуют в течение всего периода работы программы. Распределение памяти во всех этих случаях производится полностью автоматически и подчинено стековой дисциплине.

15.2 Статические переменные.

Pascal допускает возможность образовывать новые переменные в любой момент работы программы без учета ее статической структуры и допускается уничтожение созданных переменных в произвольный момент выполнения.

Переменные, созданием и уничтожением которых может явно управлять программист, называются динамическими переменными.

Динамические переменные, количество которых и место расположения в памяти заранее не известно, невозможно обозначит идентификаторами. Поэтому единственным средством доступа к динамическим переменным является указатель на место их текущего расположения в памяти. На принципе обращения к динамическим переменным посредством указателей (ссылок) на них и основаны все соответствующие средства языка Pascal.

Для распределения памяти под локальные переменные отводится специальный сегмент оперативной памяти (сегмент стека). Образование динамических переменных реализуется в другой области памяти, которая существует отдельно от стекового сегмента и называется кучей (heap) или динамической памятью.