- •Часть I. Язык Borland Pascal...................................12
- •Глава 1. Что такое программа Borland Pascal?...................12
- •Глава 2. Лексемы...............................................22
- •Глава 3. Константы.............................................32
- •Глава 4. Типы..................................................34
- •Глава 5. Переменные и типизированные константы.................72
- •Глава 6. Выражения.............................................93
- •Глава 7. Операторы............................................117
- •Глава 8. Блоки, локальность и область действия................133
- •Глава 9. Процедуры и функции..................................139
- •Глава 10. Программы и модули..................................170
- •Глава 11. Динамически компонуемые библиотеки..................180
- •Глава 12. Библиотеки исполняющей системы......................194
- •Глава 13. Стандартные процедуры и функции.....................199
- •Глава 14. Ввод и вывод........................................215
- •Глава 15. Использование сопроцессора 80x87....................248
- •Глава 16. Модуль Dоs..........................................259
- •Глава 17. Программирование в защищенном режиме dos............270
- •Глава 18. Строки с завершающим нулем..........................297
- •Глава 19. Использование графического интерфейса Borland.......308
- •Глава 20. Использование оверлеев..............................329
- •Часть III. В среде Borland Pascal.............................348
- •Глава 21. Использование памяти................................348
- •Глава 22. Вопросы управления..................................388
- •Глава 23. Автоматическая оптимизация..........................405
- •Часть IV. Использование Borland Pascal с языком ассемблера....411
- •Глава 24. Встроенный ассемблер................................411
- •Глава 25. Компоновка с программами на языке ассемблера........437
- •Часть II "Библиотеки исполняющей системы" содержит информа-
- •Часть I. Язык Borland Pascal
- •Глава 1. Что такое программа Borland Pascal?
- •Глава 2. Лексемы
- •Глава 3. Константы
- •Глава 4. Типы
- •Глава 5. Переменные и типизированные константы
- •Глава 6. Выражения
- •Глава 7. Операторы
- •Глава 8. Блоки, локальность и область действия
- •Глава 9. Процедуры и функции
- •Глава 10. Программы и модули
- •Глава 11. Динамически компонуемые библиотеки
- •Часть II. Глава 12. Библиотеки исполняющей системы
- •Глава 13. Стандартные процедуры и функции
- •Глава 14. Ввод и вывод
- •Глава 15. Использование сопроцессора 80x87
- •Глава 16. Модуль Dоs
- •Глава 17. Программирование в защищенном режиме dos
- •Глава 18. Строки с завершающим нулем
- •Глава 19. Использование графического интерфейса Borland
- •Глава 20. Использование оверлеев
- •Часть III. В среде Borland Pascal
- •Глава 21. Использование памяти
- •Глава 22. Вопросы управления
- •Глава 23. Автоматическая оптимизация
- •Часть IV. Использование Borland Pascal с языком ассемблера
- •Глава 24. Встроенный ассемблер
- •Глава 25. Компоновка с программами на языке ассемблера
Глава 5. Переменные и типизированные константы
─────────────────────────────────────────────────────────────────
Описания переменных
─────────────────────────────────────────────────────────────────
Описание переменной представляет собой список идентификато-
ров, которые обозначают новые переменные и их типы.
описание ┌────────────┐ ┌───┐ ┌───┐ ┌───┐
переменной ─>│список иден-├─>│ : ├─>│тип├─┬───────────┬─>│ ; ├>
│тификаторов │ └───┘ └───┘ │ │ └───┘
└────────────┘ │ ┌────────┐│
└>│absolute├┘
└────────┘
Тип, задаваемый для переменных, может быть идентификатором
типа, который был ранее описан в разделе описания типов того же
самого блока, или блока, в который входит данный блок, или моду-
ля, или же этот тип может быть новым определением типа.
При указании идентификатора в списке идентификаторов описа-
ния переменной этот идентификатор имеет силу идентификатора пере-
менной в том блоке, где это описание было указано. К этой пере-
менной можно обращаться из любого места этого блока, если ее
идентификатор не переопределен в блоке, входящем в первый. Пере-
определение означает, что для новой переменной используется тот
же самый идентификатор, но это использование не оказывает влияния
на значение первоначальной переменной.
Приведем пример раздела описания переменной:
var
X,Y,Z: real;
I,J,K: integer;
Digit: 0..9;
C: Color;
Done,Error: boolean;
Operator: (plus, minus, times);
Hue1,Hue2: set of Color;
Today: Date;
Results: MeasureList;
P1,P2: Person;
Matrix: array[1..10,1..10] of Real;
Переменные, описанные вне процедуры и функции, называются
глобальными переменными и располагаются в сегменте данных. Пере-
менные, описанные в самой процедуре или функции, называются ло-
кальными переменными и располагаются в сегменте стека.
B.Pascal 7 & Objects/LR - 73 -
Сегмент данных
─────────────────────────────────────────────────────────────────
Максимальный размер сегмента данных равен 65520 байт. При
компоновке программы (что автоматически осуществляется в конце
компиляции программы) глобальные переменные всех модулей, исполь-
зуемых программой, а также собственные глобальные переменные
программы, размещаются в сегменте данных.
Если для глобальных переменных требуется более 65520 байт,
то следует распределить большие структуры в виде динамических пе-
ременных. Дальнейшее описание этой темы можно найти в разделе
"Указатели и динамические переменные" настоящей главы.
Сегмент стека
─────────────────────────────────────────────────────────────────
Размер сегмента стека устанавливается с помощью директивы
компилятора $M и лежит в пределах от 1024 до 65520 байт. По умол-
чанию размер стека равен 16384 байт.
При каждой активизации (вызове) процедуры или функции в стек
помещается множество локальных переменных. При завершении работы
память, занимаемая локальными переменными, освобождается. В любой
момент выполнения программы общий размер локальных переменных в
активных процедурах и функциях не должен превышать размера сег-
мента стека.
Примечание: Если вы пишете приложение для Windows, то
Windows налагает на сегменты данных и стека специальные
требования, так что рабочий максимум стека и область сег-
мента данных могут быть меньше, чем упомянутые максимальные
области сегмента данных и стека.
Директива компилятора $S используется для проверок перепол-
нения стека в программе. В состоянии {$S+}, принятом по умолча-
нию, генерируется код, осуществляющий проверку переполнения стека
в начале каждой процедуры или функции. В состоянии {$S-} такие
проверки не проводятся. Переполнение стека может вызвать аварий-
ное завершение работы системы, поэтому не следует отменять про-
верки стека, если нет абсолютной уверенности в том, что перепол-
нения не произойдет.
B.Pascal 7 & Objects/LR - 74 -
Абсолютные переменные
─────────────────────────────────────────────────────────────────
Переменные можно описать так, что они будут располагаться по
определенному адресу в памяти, и в этом случае они называются аб-
солютными переменными. Описание таких переменных должно содержать
после типа оператор absolute:
описание ┌────────┐ ┌─────────┐ ┌───┐ ┌─────────┐
абсолютной ───>│absolute├─┬─>│целое без├─>│ : ├─>│целое без├─┬─>
переменной └────────┘ │ │ знака │ └───┘ │ знака │ │
│ └─────────┘ └─────────┘ │
│ ┌─────────────┐ │
└──────>│идентификатор├────────────┘
│ переменной │
└─────────────┘
Отметим, что список идентификаторов в описании переменной
при указании оператора absolute может содержать только один иден-
тификатор.
Первая часть оператора absolute содержит сегмент и смещение,
то есть адрес, по которому переменная должна быть размещена.
CrtMode : byte absolute $0040:$0049;
Первая константа обозначает базу сегмента, а вторая опреде-
ляет смещение внутри этого сегмента. Обе константы не должны вы-
ходить за пределы диапазона от $0000 до $FFFF (от 0 до 65535).
В программах защищенного режима DOS и в Windows первую форму
оператор absolute нужно использовать очень аккуратно, если вообще
стоит это делать. Во время выполнения прикладной программы
Windows или DOS защищенного режима она может не иметь полномочий
доступа к областям памяти вне вашей программы. Попытка доступа к
этим областям памяти может привести к сбою программы.
B.Pascal 7 & Objects/LR - 75 -
Вторая форма оператора absolute используется для описания
переменной, которая помещается "поверх" другой переменной, то
есть по тому же самому адресу, что и другая переменная.
var
Str: string[32];
StrLen: byte absolute Str;
Это описание указывает, что переменная StrLen должна разме-
щаться с того же адреса, что и переменная Str, а поскольку первый
байт строковой переменной содержит динамическую длину строки, то
StrLen будет содержать длину Str.
Эту вторую форму оператора absolute можно без опасения ис-
пользовать при программировании в Windows или в защищенном режиме
DOS. Память, к которой вы обращаетесь, находится в области прог-
раммы.
B.Pascal 7 & Objects/LR - 76 -
Ссылки на переменные
─────────────────────────────────────────────────────────────────
Ссылка на переменную может обозначать следующее:
- переменную;
- компонент в переменной структурного или строкового типа;
- динамическую переменную, на которую указывает переменная
типa указатель.
Синтаксис ссылки на переменную имеет вид:
┌─────────────┐
ссылка на ─┬──>│идентификатор├────────────────────────────┬──>
переменную │ │ переменной │ ^^ ┌────────────┐ │
│ └─────────────┘ │└──┤квалификатор│<─┘
│ ┌───────────────┐ │ └────────────┘
├──>│приведение типа├──────┤
│ │ переменной │ │
│ └───────────────┘ └─────┐
│ ┌─────────┐ ┌────────────┐ │
└──>│выражение├─>│квалификатор├──┘
└─────────┘ └────────────┘
Отметим, что синтаксис ссылки на переменную допускает ис-
пользование выражения, вычисляющего значение ссылочного типа. Вы-
ражение должно следовать за квалификатором, разыменовывающим ссы-
лочное значение (или индексирующим значением указателя, если с
помощью директивы {$X+} разрешен расширенный синтаксис), что дает
фактическую ссылку на переменную.
B.Pascal 7 & Objects/LR - 77 -
Квалификаторы
─────────────────────────────────────────────────────────────────
Обращение к функции представляет собой идентификатор пере-
менной с несколькими квалификаторами или без них, которые изменя-
ют значение обращения к функции.
┌──────┐
квалификатор ──┬──>│индекс├──────────>
│ └──────┘ ^
│ ┌────────────┐ │
├──>│ десигнатор ├──┤
│ │ поля │ │
│ └────────────┘ │
│ ┌───┐ │
└──>│ ^ ├───────────┘
└───┘
Идентификатор массива без квалификатора является ссылкой на
весь массив, например:
Results
Идентификатор массива с указанным индексом обозначает конк-
ретный элемент массива, в данном случае структурную переменную:
Results[Current+1]
В случае, если элементом является запись, за индексом можно
указать обозначение поля. В этом случае ссылка на переменную оз-
начает конкретное поле конкретного элемента массива:
Results[Current+1].Data
Десигнатор поля в указателе-поле может сопровождаться сим-
волом указателя (^) с тем, чтобы указать различие между указате-
лем-полем и динамической переменной, на которую он указывает.
Results[Current+1].Data^
Если переменная, на которую указывается, является массивом,
то можно добавить индексы для обозначения компонентов этого мас-
сива.
Results[Current+1].Data^[J]
B.Pascal 7 & Objects/LR - 78 -
Массивы, строки и индексы
─────────────────────────────────────────────────────────────────
Конкретный элемент массива обозначается с помощью ссылки на
переменную массива, за которой указывается индекс, определяющий
данный элемент.
Конкретный символ в строковой переменной обозначается с по-
мощью ссылки на строковую переменную, за которой указывается ин-
декс, определяющий позицию символа.
┌───┐ ┌─────────┐ ┌───┐
индекс ──>│ [ ├───────>│выражение├────┬──>│ ] ├──>
└───┘ ^ └─────────┘ │ └───┘
│ ┌───┐ │
└───────┤ , │<───────┘
└───┘
Индексные выражения обозначают компоненты в соответствующей
размерности массива. Число выражений не должно превышать числа
индексных типов в описании массива. Более того, тип каждого выра-
жения должен быть совместимым по присваиванию с соответствующим
индексным типом.
В случае многомерного массива можно использовать несколько
индексов или несколько выражений в индексе. Например:
Matrix[I][J]
что тождественно записи:
Matrix[I,J]
Строковую переменную можно проиндексировать с помощью оди-
ночного индексного выражения, значение которого должно быть в ди-
апазоне 0...n, где n - указанный в описании размер строки. Это
дает доступ к каждому символу в строковом значении, если значение
символа имеет тип Char.
Первый символ строковой переменной (индекс 0) содержит дина-
мическую длину строки, то есть Length(S) тождественно Ord(S[0]).
Если атрибуту длины присваивается значение, то компилятор не про-
веряет, является ли это значение меньшим описанного размера стро-
ки. Вы можете указать индекс строки и вне ее текущей динамической
длины. В этом случае считываемые символы будут случайными, а
присваивания вне текущей длины не повлияют на действительное зна-
чение строковой переменной.
Когда с помощью директивы компилятора {$X+} разрешен расши-
ренный синтаксис, значение PChar может индексироваться одиночным
индексным выражением типа Word. Индексное выражение задает смеще-
ние, которое нужно добавить к символу перед его разыменованием
для получения ссылки на переменную типа Char.
B.Pascal 7 & Objects/LR - 79 -
Записи и десигнаторы полей
─────────────────────────────────────────────────────────────────
Конкретное поле переменной-записи обозначается с помощью
ссылки на переменную-запись, после которой указывается обозначе-
ние поля, специфицирующее это поле.
┌───┐ ┌─────────────┐
обозначение поля ───>│ . │───>│идентификатор│───>
└───┘ │ поля │
└─────────────┘
Приведем несколько примеров десигнаторов полей:
Today.Year
Results[1].Count
Result[1].When.Month
В операторе, входящем в оператор with, обозначению поля не
должна предшествовать ссылка на переменную, содержащую запись.
Десигнаторы компонентов объекта
─────────────────────────────────────────────────────────────────
Формат десигнатора компонента объекта совпадает с форматом
десигнатора поля записи. То есть, он состоит из экземпляра (ссыл-
ки на переменную), за которым следует точка и идентификатор ком-
понента. Десигнатор компонента, который обозначает метод, называ-
ется десигнатором метода. К экземпляру объектного типа можно
применить оператор with. В этом случае при ссылке на компоненты
объектного типа экземпляр и точку можно опустить.
Экземпляр и точку можно опустить также в любом блоке метода.
При этом эффект будет тот же, что и при записи перед ссылкой на
компонент Self и точки.
Переменные-указатели и динамические переменные
─────────────────────────────────────────────────────────────────
Значением переменной-указателя является или nil (то есть
пустое значение), или адрес значения, указывающий на динамическую
переменную.
Ссылка на динамическую переменную, на которую указывает пе-
ременная-указатель, записывается в виде переменной-указателя,
после которой ставится символ указателя (^).
Динамические переменные и значения их указателей создаются с
помощью стандартных процедур New и GetMem. Вы можете использовать
B.Pascal 7 & Objects/LR - 80 -
операцию @ и стандартную функцию Ptr для создания значений указа-
теля, которые рассматриваются как указатели динамических перемен-
ных.
Значение nil не указывает ни на какую переменную. Если вы
попытаетесь получить доступ к динамической переменной при неопре-
деленном значении указателя или указателе, равном nil, результат
будет неопределенным.
Приведем несколько примеров ссылок (указателей) на динами-
ческие переменные:
P1^
P1.Sibling^
Results[1].Data^
B.Pascal 7 & Objects/LR - 81 -
Приведение типов переменных
─────────────────────────────────────────────────────────────────
Ссылка на переменную одного типа может быть преобразована в
ссылку на переменную другого типа с помощью приведения типов пе-
ременных.
┌─────────────┐ ┌───┐ ┌──────────┐ ┌───┐
приведение ───>│идентификатор├──>│ ( ├──>│ссылка на ├──>│ ) ├─>
типов │ типа │ └───┘ │переменную│ └───┘
└─────────────┘ └──────────┘
Когда приведение типов применяется к ссылке на переменную,
ссылка на переменную рассматривается как экземпляр типа, предс-
тавленного идентификатором типа. Размер переменной (число байт,
занимаемых переменной) должен быть равен размеру типа, представ-
ленного идентификатором типа. После приведения типа переменной
можно указать один или несколько квалификаторов, если это допус-
кается указанным типом.
Примечание: Определять допустимость приведения типа
должен программист.
Приведем несколько примеров приведения типов переменных:
type
TByteRec = record
lo, hi: byte;
end;
TWordRec = record
low, high: word;
end;
TPtrRec = record
ofs, seg: word;
end;
PByte = ^Byte;
var
B: byte;
W: word;
L: longint;
P: pointer;
begin
W := $1234;
B := TByteRec(W).lo;
TByteRec(W).hi := 0;
L := $1234567;
W := TWordRec(L).lo;
B := PByte(L)^;
P := Ptr($40,$49);
W := TPtrRec(P).seg;
Inc(TPtrRec(P).Ofs,4);
end.
B.Pascal 7 & Objects/LR - 82 -
Обратите внимание на использование для доступа к младшим и
старшим байтам слова типа TByteRec: это соответствует встроенным
функциям Lo и Hi, только над левой частью в операции присваивание
может выполняться приведение типа. Отметим также, что для доступа
к младшим и старшим словам длинного целого, а также к смещению и
адресу сегмента указателя используются типы TWordRec и TPtrRec.
Borland Pascal также полностью поддерживает приведение типов
для процедурных типов. Например, имея следующие описания:
type
Func = function(X: Integer): Integer;
var
F: Func;
P: Pointer;
N: Integer;
вы можете построить следующие присваивания:
F := Func(P); { присвоить F значение процедурного типа в P }
Func(P) := F; { присвоить P значение процедурного типа в F }
@F := P; { присвоить F значение-указатель в P }
P := @F; { присвоить P значение-указатель в F }
N := F(N); { вызвать функцию через F }
N := Func(P)(N); { вызвать функцию через P }
Обратите в частности внимание на операцию получения адреса
@, которая применяется к переменной процедурного типа. Ее можно
использовать в левой части присваивания. Кроме того, отметьте
приведение типа на последней строке при вызове функцию через пе-
ременную-указатель.
B.Pascal 7 & Objects/LR - 83 -
Типизированные константы
─────────────────────────────────────────────────────────────────
Типизированные константы можно сравнить с инициализированны-
ми переменными - переменными, значения которых определяются на
входе в их блок. В отличие от нетипизированных констант в описа-
нии типизированной константы указывается как тип, так и значение
константы.
описание типизированной константы
│ ┌─────────────┐ ┌───┐ ┌───┐ ┌───┐ ┌──────────────┐
└─>│идентификатор├─>│ : ├─>│тип├─>│ = ├─>│типизированная├──>
└─────────────┘ └───┘ └───┘ └───┘ │ константа │
└──────────────┘
типизированная ┌───────────────────┐
константа ──────┬───>│ константа ├───────>
│ └───────────────────┘ ^
│ ┌───────────────────┐ │
├───>│ адресная константа├───┤
│ └───────────────────┘ │
│ ┌───────────────────┐ │
├───>│ константа-массив ├───┤
│ └───────────────────┘ │
│ ┌──────────────────┐ │
├───>│ константа-запись ├────┤
│ └──────────────────┘ │
│ ┌───────────────────┐ │
├───>│ константа-объект ├───┤
│ └───────────────────┘ │
│ ┌───────────────────┐ │
└───>│константа-множество├───┘
└───────────────────┘
Типизированные константы можно использовать точно так же,
как переменные того же самого типа, и они указываются в левой
части оператора присваивания. Отметим, что типизированные конс-
танты инициализируются только один раз - в начале выполнения
программы. Таким образом, при каждом новом входе в процедуру или
функцию локально описанные типизированные константы заново не
инициализируются.
Кроме обычных выражений-констант значение типизированной
константы может задаваться с помощью адресного выражения-констан-
ты. Адресное выражение-константа - это выражение, предусматриваю-
щее получение адреса, смещения или сегмента глобальной перемен-
ной, типизированной константы, процедуры или функции. Адресные
выражения-константы не могут ссылаться на локальные переменные
(расположенные в стеке) или динамические переменные (размещенные
в динамически распределяемой области памяти), поскольку их адреса
нельзя вычислить на этапе компиляции.
B.Pascal 7 & Objects/LR - 84 -
Константы простого типа
─────────────────────────────────────────────────────────────────
Описание типизированной константы с простым типом означает
указание значения константы:
const
Maximum : integer = 9999;
Factor : real = -0.1;
Breakchar : char = #3;
Как уже упоминалось ранее, значение типизированной константы
можно задать с помощью адресного выражение-константы, то есть вы-
ражения, в котором используются адрес, смещение или сегмент гло-
бальной переменной, типизированной константы, процедуры или функ-
ции. Например:
var
Buffer: array[0..1023] of Byte;
const
BufferOfs: Word = Ofs(Buffer);
BufferSeg: Word = Seg(Buffer);
Поскольку типизированная константа фактически представляет
собой переменную со значением константы, она не является взаимо-
заменяемой для обычных констант. Например, она не может использо-
ваться в описании других констант или типов.
const
Min : integer = 0;
Max : integer = 99;
type
Vector = array[Min..Max] of integer;
Описание Vector является недопустимым, поскольку Min и Max
являются типизированными константами.
Константы строкового типа
─────────────────────────────────────────────────────────────────
Описание типизированной константы строкового типа содержит
максимальную длину строки и ее начальное значение:
const
Heading : string[7] = 'Section';
NewLine : string[2] = #13#10;
TrueStr : string[5] = 'Yes';
FalseStr : string[5] = 'No';
B.Pascal 7 & Objects/LR - 85 -
Константы структурного типа
─────────────────────────────────────────────────────────────────
Описание константы структурного типа определяет значение
каждого компонента структуры. Borland Pascal поддерживает описа-
ния констант типа массив, запись, множество и указатель. Констан-
ты файлового типа и константы типа массив или запись, содержащие
компоненты файлового типа, не допускаются.
B.Pascal 7 & Objects/LR - 86 -
Константы типа массив
─────────────────────────────────────────────────────────────────
Описание константы типа массив содержит значения элементов,
заключенные в скобки и разделенные запятыми.
┌───┐ ┌──────────────┐ ┌───┐
константа-массив ───>│ ( ├────>│типизированная├──┬─>│ ) ├──>
└───┘ ^ │ константа │ │ └───┘
│ └──────────────┘ │
│ ┌───┐ │
└──────┤ , │<────────┘
└───┘
Приведем пример константы типа массив:
type
Status = (Active,Passive,Waiting);
StatusMap = array[Status] of string[7];
const
StatStr: StatusMap = ('Active','Passive','Waiting');
В этом примере определяется константа-массив StarStr, кото-
рая может использоваться для преобразования значений типа Status
в соответствующие им строковые представления. Элементами массива
StarStr являются:
StatStr[Active] = 'Active'
StatStr[Passive] = 'Passive'
StatStr[Waiting] = 'Waiting'
Тип элемента константы-массива может быть любым, кроме фай-
лового типа. Упакованные константы строкового типа (символьные
массивы) могут быть определены и как одиночные символы, и как
строки. Определение:
const
Digits:array[0..9] of
char=('0','1','2','3','4','5','6','7','8','9');
можно представить в более удобном виде:
const
Digits: array[0..9] of char = '0123456789';
При разрешении расширенного синтаксиса (с помощью директивы
компилятора {$X+}) массивы с нулевой базой могут инициализирова-
ться строкой, которая короче, чем описанная длина массива, напри-
мер:
const
FileName = array[0..79] of Char = 'TEXT.PAS';
B.Pascal 7 & Objects/LR - 87 -
В таких случаях оставшиеся символы устанавливаются в NULL
(#0), и массив содержит строку с завершающим нулем.
Примечание: Подробнее о строках с завершающим нулем
рассказывается в Главе 18.
При описании константы типа "многомерный массив" константы
каждой размерности заключаются в отдельные скобки и разделяются
запятыми. Расположенные в середине константы соответствуют самым
правым размерностям. Описание:
type
Cube = array[0..1,0..1,0..1] of integer;
const
Maze: Cube = (((0,1),(2,3)),((4,5),(6,7)));
задает следующие начальные значения массива Maze:
Maze[0, 0, 0] = 0
Maze[0, 0, 1] = 1
Maze[0, 1, 0] = 2
Maze[0, 1, 1] = 3
Maze[1, 0, 0] = 4
Maze[1, 0, 1] = 5
Maze[1, 1, 0] = 6
Maze[1, 1, 1] = 7
B.Pascal 7 & Objects/LR - 88 -
Константы типа запись
─────────────────────────────────────────────────────────────────
Описание константы типа запись содержит идентификатор и зна-
чение каждого поля, заключенные в скобки и разделенные точками с
запятой.
константа-запись
│ ┌───┐ ┌─────────────┐ ┌───┐ ┌──────────────┐ ┌───┐
└─>│ ( ├───>│идентификатор├─>│ : ├─>│типизированная├─┬─>│ ) ├─>
└───┘ ^ │ поля │ └───┘ │ константа │ │ └───┘
│ └─────────────┘ └──────────────┘ │
│ ┌───┐ │
└───────────────────┤ ; │<──────────────────┘
└───┘
Приведем несколько примеров констант-записей:
type
Point = record
x,y: real;
end;
Vector = array[0..1] of Point;
Month =
(Jan,Feb,Mar,Apr,May,Jun,Jly,Aug,Sep,Oct,Nov,Dec);
Date = record
d: 1..31; m: Month; y: 1900..1999;
end;
const
Origin : Point = (x: 0.0; y: 0.0);
Line : Vector = ((x: -3.1; y: 1.5),(x: 5.8; y: 3.0));
SomeDay : Date = (d: 2; m: Dec; y: 1960);
Поля должны указываться в том же порядке, как они следуют в
описании типа запись. Если запись содержит поля файлового типа,
то для этого типа запись нельзя описать константу. Если запись
содержит вариант, то можно указывать только поля выбранного вари-
анта. Если вариант содержит поле признака, то его значение должно
быть определено.
B.Pascal 7 & Objects/LR - 89 -
Константы объектного типа
─────────────────────────────────────────────────────────────────
При описании константы объектного типа используется тот же
синтаксис, что и при описании константы типа запись. Значения для
элементов (компонентов) метода задаваться не могут. С учетом при-
водимых ранее описаний объектных типов, приведем некоторые приме-
ры констант объектного типа:
const
ZeroPoint: Point = (X: 0; Y: 0)
ScreenRect: Rect = (A: (X: 0; Y: 0); B: (X: 80; Y: 25);
CountField: NumField = (X: 5; Y: 20; Len: 4; Name: nil;
Value: 0; Min: -999; Max: 999);
Константы объектного типа, которые содержат виртуальные ме-
тоды, не требуется инициализировать с помощью вызова конструкто-
ра. Эта инициализация автоматически выполняется компилятором.
B.Pascal 7 & Objects/LR - 90 -
Константы множественного типа
─────────────────────────────────────────────────────────────────
Описание константы множественного типа может содержать нес-
колько элементов, заключенных в квадратные скобки и разделенных
запятыми. Каждый элемент такой константы представляет собой конс-
танту или отрезок типа, состоящий из двух констант, разделенных
двумя точками.
┌───┐ ┌───┐
константа-множество ─>│ [ ├─┬────────────────────────────>│ ] ├>
└───┘ │ ┌─────────────────┐ ^ └───┘
└───>│константа-элемент├─┬─┘
^ └─────────────────┘ │
│ ┌───┐ │
└────────┤ , │<────────┘
└───┘
┌─────────┐
константа-элемент ────>│константа├──┬─────────────────────────>
└─────────┘ │ ┌──┐ ┌─────────┐ ^
└─>│..├──>│константа├──┘
└──┘ └─────────┘
Приведем несколько примеров констант-множеств:
type
Digits = set of 0..9;
Letters = set of 'A'..'Z';
const
EvenDigits: Digits = [0,2,4,6,8];
Vowels : Letters = ['A','E','I','O','U','Y'];
HexDigits : set of '0'..'z' =
['0'..'9','A'..'F','a'..'f'];
B.Pascal 7 & Objects/LR - 91 -
Константы ссылочного типа
─────────────────────────────────────────────────────────────────
Описание константы ссылочного типа может содержать только
значение nil (пусто). Приведем несколько примеров:
type
TDirection = (Left, Right, Up, Down);
TStringPtr = ^String;
TNodePtr = ^Node;
TNode = record
Next: NodePtr;
Symbol: StringPtr;
Value: Direction;
end;
const
S1: string[4] = 'DOWN';
S2: string[2] = 'UP';
S3: string[5] = 'RIGHT';
S4: string[4] = 'LEFT';
N1: Node = (Next: nil; Symbol: @S1; Value: Down);
N2: Node = (Next: @N1; Symbol: @S2; Value: Up);
N3: Node = (Next: @N2; Symbol: @S3; Value: Right);
N2: Node = (Next: @N3; Symbol: @S4; Value: Left);
DirectionTable: NodePtr = @N4;
Если разрешен расширенный синтаксис (указана директива ком-
пилятора {$X+}), типизированная константа типа PChar может иници-
ализироваться строковой константой, например:
const
Message: PChar = 'Программа завершена';
Prompt: PChar = 'Введите значения: ';
Digits: array[0..9] of PChar = (
'Ноль', 'Один', 'Два', 'Три', 'Четыре',
'Пять', 'Шесть', 'Семь', 'Восемь', 'Девять');
Результатом будет то, что указатель теперь указывает на об-
ласть памяти, содержащую копию строкового литерала с завершающим
нулем. Подробности вы можете найти в Главе 18 "Строки с завершаю-
щим нулем".
B.Pascal 7 & Objects/LR - 92 -
Константы процедурного типа
─────────────────────────────────────────────────────────────────
Константы процедурного типа должны определять идентификатор
процедуры или функции, совместимый по присваиванию с типом конс-
танты.
┌─────────────────┐
процедурная константа ──────┬───>│константа-элемент├───────────>
│ └─────────────────┘ ^
│ ┌─────────────────┐ │
├───>│константа-элемент├───┤
│ └─────────────────┘ │
│ ┌───┐ │
└─────────>│nil├───────────┘
└───┘
Приведем следующий пример:
type
ErrorProc = procedure(ErrorCode: Integer);
procedure DefaultError(ErrorCode: Integer); far;
begin
WriteLn('Error ', ErrorCode, '.');
end;
const
ErrorHandler: ErrorProc = DefaultError;
B.Pascal 7 & Objects/LR - 93 -
───────────────────────────────────────────────────────────────────────