Volume(Radius, Height)
В режиме расширенного синтаксиса ($X+) вызовы функций можно
использовать в качестве операторов, то есть результат вызова
функции может отбрасываться.
B.Pascal 7 & Objects/LR - 113 -
Описатели множества
─────────────────────────────────────────────────────────────────
Описатель множества определяет значения множественного типа
и получается путем записи выражений, заключенных в квадратные
скобки ([]). Каждое выражение определяет значение множества.
┌───┐ ┌───┐
описатель ───>│ [ ├──┬────────────────────────>│ ] ├───>
множества └───┘ │ ┌────────────┐ ^ └───┘
└───>│ группа ├──┬─┘
^ │ элементов │ │
│ └────────────┘ │
│ ┌───┐ │
└────┤ , │<────────┘
└───┘
┌───────────┐
группа элементов ──>│ выражение ├──┬───────────────────────────>
└───────────┘ │ ^
│ ┌──┐ ┌───────────┐ │
└─>│..├──>│ выражение ├─┘
└──┘ └───────────┘
Обозначение [ ] означает пустое множество, тип которого сов-
местим по присваиванию с типом любого множества. Любая группа
элементов, описанная, как х..у, объявляет элементами множества
все значения в диапазоне х..у. Если х больше, чем у, то х..у не
описывает никаких элементов и [x..y] обозначает пустое множество.
В конкретном описателе множества все значения выражения в
группах элементов должны быть одного порядкового типа.
Приведем некоторые примеры описателей множеств:
[red, C, green]
[1,5,10..K mod 12, 13, 23]
['A'..'Z', 'a'..'z', Chr(Digit+48)]
B.Pascal 7 & Objects/LR - 114 -
Приведение типа значений
─────────────────────────────────────────────────────────────────
Тип выражения можно изменить на другой тип с помощью приве-
дения типа значений.
┌─────────────┐ ┌───┐ ┌─────────┐ ┌───┐
приведение ───>│идентификатор├──>│ ( ├──>│выражение├──>│ ) ├─>
типа значения │ типа │ └───┘ └─────────┘ └───┘
└─────────────┘
Тип выражения и задаваемый тип должны оба иметь перечислимый
тип или тип указателей. Для перечислимых типов результирующее
значение получается путем преобразования выражения (и возможной
проверки на нахождение в допустимых границах). Преобразование мо-
жет привести к усечению или увеличению размера исходного значения
в том случае, если вновь определяемый тип отличается от типа вы-
ражения. В том случае, когда значение расширяется, его знак всег-
да сохраняется. Таким образом, значение является расширяемым по
знаку.
Синтаксис приведения типа значений почти совпадает с синтак-
сисом приведения типа переменных (см. раздел "Приведение типа пе-
ременных" в Главе 5). Однако при приведении типа значений опера-
ции производятся со значениями, а не с переменными и, таким
образом, могут не участвовать в ссылках на переменные. То есть за
приведением типа значения не обязательно следуют квалификаторы. В
частности, приведение типа значений не должно встречаться в левой
части оператора присваивания.
Некоторые примеры приведения типа значений включают в себя:
Intereg('A')
Char(48)
Boolean(0)
Color(2)
IntPtr(@Buffer)
BytePtr(Ptr($40,$49))
B.Pascal 7 & Objects/LR - 115 -
Процедурные типы в выражениях
─────────────────────────────────────────────────────────────────
В общем случае использование процедурной переменной в опера-
торе или выражении означает вызов процедуры или функции, храня-
щейся в этой переменной. Однако, имеется исключение. Когда компи-
лятор видит, что процедурная переменная находится в левой части
оператора присваивания, он знает, что правая часть должна предс-
тавлять собой процедурное значение. Рассмотрим в качестве примера
следующую программу:
type
IntFunc = function: Integer;
var
F: IntFunc;
N: Integer;
function ReadInt: Integer; far;
var
I: Integer;
begin
Read(I);
ReadInt := I;
end;
begin
F := ReadInt; { присваивание процедурного значения }
N := ReadInt; { присваивание результата функции }
end.
Первый оператор основной программы присваивает процедурное
значение (адрес процедуры) ReadInt процедурной переменной F, вто-
рой оператор вызывает ReadInt и присваивает N возвращаемое значе-
ние. Различие между получением процедурного значения или вызовом
функции осуществляется по типу переменной, которой присваивается
значение (F или N).
К сожалению, есть ситуации, когда компилятор не может опре-
делить из контекста желаемое действие. Например, в следующем опе-
раторе для компилятора не очевидно, что нужно сделать: сравнить
процедурное значение в F с процедурным значением ReadInt, чтобы
определить, что F указывает в данный момент на ReadInt, или выз-
вать F и ReadInt, а затем сравнить возвращаемые значения:
if F = ReadInt then
WriteLn('Equal');
Однако, стандартный синтаксис Паскаля определяет, что вхож-
дение в выражение идентификатора функции означает вызов этой
функции, поэтому в результате предыдущего оператора будет выпол-
нен вызов F и ReadInt, а затем будут сравниваться возвращаемые
значения. Чтобы сравнить процедурное значение в F с процедурным
значением в ReadInt, нужно использовать следующую конструкцию:
B.Pascal 7 & Objects/LR - 116 -
if @F = @ReadInt then
WriteLn('Equal');
При применении к процедурной переменной, идентификатору про-
цедуры или функции операции получения адреса @, эта операция пре-
дотвращает вызов компилятором процедуры и в то же время преобра-
зует аргумент в указатель. Таким образом, @F преобразует F в не-
типизованный указатель-переменную, которая содержит адрес
ReadInt. Для определения того, что F ссылается на ReadInt можно
сравнить два значения-указателя.
Операция @ часто используется при присваивании процедурной
переменной нетипизированного значения-указателя. Например, опре-
деленная в Windows (в модуле WinProcs) функция GetProcAddress
возвращает адрес экспортируемой функции в DLL как нетипизирован-
ной значение-указатель. С помощью операции @ вызов GetProcAddress
можно присвоить процедурной переменной:
type
TStrComp = function(Str1, Str2: PChar): Integer;
var
StrComp: TStrComp:
.
.
.
begin
.
.
.
@StrComp := GetProcAddress(KernelHandle, 'Lstrcmpi');
.
.
.
end.
Чтобы получить адрес в памяти процедурной переменной, а не
адрес, в ней записанный, используйте двойную операцию @ (@@).
Например, @P означает преобразование P в нетипизированный указа-
тель-переменную, в @@P означает возвращение физического адреса
переменной P.
B.Pascal 7 & Objects/LR - 117 -
───────────────────────────────────────────────────────────────────────
