Рассмотрим действие оператора @ с различными типами переменных. При использовании с глобальными переменными или типизированными константами оператор вернет адрес этих переменных, как правило, в сегменте данных. При использовании его внутри процедур и функций с параметрами-переменными оператор @
- 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 -
Но в чистом виде такая конструкция имеет мало смысла, ибо не определена структура, на первый байт которой указывает это разыменование. А определить эту структуру можно операцией приведения (преобразования) типа:
B := Byte( Ptr($40, $40)^); {B — значения байта $40:$40 }
W := Word( Ptr($40,$40)^ ); { W — значение слова $40:$40 }
X := VideoArray( Ptr($B800,0)^); { X — статический массив типа VideoArray содержит теперь в себе образ видеопамяти (текстовое изображение) }
и т.д.
Не стоит только приводить к типу String и производным от него: никогда не известно, что окажется в нулевом элементе строки, где должен храниться ее реальный размер.
10.5.3. Определение размеров типов и переменных
Функция SizeOf(X): Word возвращает объем в байтах, занимаемый X. Причем X может быть не только переменной, но также и идентификатором типа (рис. 10.3).
| TYPE
| XType = Array[1..10, 1..10] of byte;
|CONST
| L : Longint = 123456;
| VAR
| X : String;
| BEGIN
| WriteLn(SizeOf(Xtype): 10, SizeOf(L): 10, SizeOf(X))
| END.
Рис. 10.3
Значение SizeOf(строка) всегда дает максимальное значение длины строки. Реальное значение дает функция Length.
Вообще говоря, функцию SizeOf можно рассматривать как макроподстановку размеров типов и переменных, вычисляемых на этапе компиляции.
Применительно к данным типа «объект» (OBJECT) эта функцию должна использоваться более осторожно, так как у объектов может не быть заранее предопределяемого размера. Обсуждение этого можно найти в гл. 13.
Глава 11. Ссылки, динамические переменные и структуры
Динамическими структурами данных считаются такие, размер которых в процессе работы программы заранее не известен или изменяется и(или) для которых место в памяти ПЭВМ отводится во время выполнения программы. Необходимость в динамических структурах данных обычно возникает в следующих случаях:
1. Используются переменные, имеющие довольно большой размер, необходимые в одни частях программы и совершенно не нужные в других, т.е. переменные, освобождающие память после их использования.
2. В процессе работы программы нужен массив или иная структура, размер которой изменяется в широких пределах и труднопредсказуем.
Кроме этих двух случаев, общих для различных версий Паскаля, при программировании на Турбо Паскале есть еще один. А именно: когда размер переменной (массива или записи) превышает 64 К.
Во всех этих случаях возникающие проблемы можно решить, применяя динамические переменные и ссылочные типы данных.
11.1. Ссылочные переменные