Программирование в среде Турбо Паскаль (Поляков, Круглов) - страница 123

Заметим, что если P — ссылка, то Addr(P) или @P, а также Seg(P) и Ofs(P) вернут адрес или сегмент со смещением самой переменной-ссылки P в области статических данных, но Addr(P^) или @Р^ и Seg(P^) с Ofs(P^) возвратят содержимое ссылки P, т.е.

Р = Addr( Р^).

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

- 192 -

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


10.5.2. Создание адреса функцией Ptr


Функция Ptr( Seg, Ofs : Word) выполняет противоположную функции Addr работу: организует ссылку на место в памяти, определяемое заданными сегментом и смещением. Необходимость в такой функции возникает всякий раз, когда требуется наложить динамическую структуру на системную область памяти (системные, т.е. зарезервированные, области памяти достаточно жестко фиксированы, и их адреса описаны в специальной литературе). Если, например, известно, что образ текстового экрана начинается с адреса $В000 : $0000 и занимает 4000 байт (цветной и черно-белый режимы, 80 столбцов на 25 строк), то можно «наложить» на него структуру, например массив, используя ссылку на такой массив и функцию Ptr (рис. 10.2):


| TYPE

| >VideoArray = Array [0..3999] of Byte;

| VAR

| >V : ^VideoArray; { ссылка на структуру }

| BEGIN

| >V := Ptr( $B000, 0 );

| >{ Далее V^[i] обращается непосредственно к ячейкам видеопамяти в текстовом режиме }

| >...

| END.


Рис. 10.2

Обращаем внимание на отсутствие вызовов New и Dispose. Они не нужны, так как массив буквально накладывается, а не создается вновь.

Так как значение типа Pointer, возвращаемое функцией Ptr, совместимо со всеми ссылочными типами, можно наложить любую структуру на какой угодно участок памяти. Кроме того, его разрешается разыменовывать, т.е. записывать конструкции вида

Ptr( $40, $40 )^

- 193 -

Но в чистом виде такая конструкция имеет мало смысла, ибо не определена структура, на первый байт которой указывает это разыменование. А определить эту структуру можно операцией приведения (преобразования) типа: