10.5.1. Определение адреса переменных
Функции Addr(X), Seg(X) и Ofs(X), а также оператор @ возвращают адрес объекта X или компоненты адреса. Под X можно понимать любой объект: переменные любых типов, объекты, процедуры и функции (но не константы).
Функция Addr(X) и оператор @ возвращают значение типа Pointer — адрес объекта X. Их действие одинаково:
VAR
X : String; p, q : Pointer;
...
р: = Addr( X );
q: = @X;
{Теперь p=q, и адреса равны; они указывают на один объект }
Значение типа Pointer не может быть выведено на экран. Но так как этот тип состоит из двух слов (Word), хранящих сегмент и смещение, можно вывести их в отдельности, используя функции Seg и Ofs (обе типа Word):
WriteLn( 'Сегмент ', Seg( р ), ' смещение ', Ofs( р ));
В то же время значения ссылок можно получить в режиме отладки. Они будут выводиться в окна наблюдения и модификации (Watch и Evaluate).
Может возникнуть вопрос — а зачем вообще нужна функция Addr, если есть Seg и Ofs, тем более что нельзя распечатать ее значение? Ответ: функция Addr и оператор @ нужны для привязывания ссылок, т.е. динамических переменных, к статическим данным, а также для работы с массивами данных в виде OBJ-файлов, связанных с выполнимым файлом на этапе компоновки. Пример компоновки внешних данных дан при описании работы с образом экрана на диске в разд. 20.4 «Работа с образом экрана на диске».
Заметим, что если P — ссылка, то Addr(P) или @P, а также Seg(P) и Ofs(P) вернут адрес или сегмент со смещением самой переменной-ссылки P в области статических данных, но Addr(P^) или @Р^ и Seg(P^) с Ofs(P^) возвратят содержимое ссылки P, т.е.
Р = Addr( Р^).
Рассмотрим действие оператора @ с различными типами переменных. При использовании с глобальными переменными или типизированными константами оператор вернет адрес этих переменных, как правило, в сегменте данных. При использовании его внутри процедур и функций с параметрами-переменными оператор @
- 192 -
применительно к ним вернет адреса фактических переменных, подставленных в вызов процедуры или функции. Но применение оператора @ к параметру-значению, как и к любой локальной переменной, даст адрес в стеке, где временно расположено значение. Можно применять этот оператор и к идентификаторам процедур и функций (это даст точку входа в процедуру или функцию), но что с ней потом делать, не привлекая вставки на ассемблере, неясно.