Глава 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;

 

             Переменные, описанные  вне  процедуры и функции,  называются

        глобальными переменными и располагаются в сегменте данных.  Пере-

        менные,  описанные в самой процедуре или функции,  называются ло-

        кальными переменными и располагаются в сегменте стека.

Сегмент данных

             Максимальный размер  сегмента  данных равен 65520 байт.  При

        компоновке программы (что автоматически  осуществляется  в  конце

        компиляции программы) глобальные переменные всех модулей, исполь-

        зуемых программой,  а  также  собственные  глобальные  переменные

        программы, размещаются в сегменте данных.

 

             Если для  глобальных  переменных требуется более 65520 байт,

        то следует распределить большие структуры в виде динамических пе-

        ременных. Дальнейшее описание этой темы  можно  найти  в  разделе

        "Указатели и динамические переменные" настоящей главы.

Сегмент стека

             Размер сегмента стека устанавливается  с  помощью  директивы

        компилятора $M и лежит в пределах от 1024 до 65520 байт. По умол-

        чанию размер стека равен 16384 байт.

 

             При каждой активизации (вызове) процедуры или функции в стек

        помещается множество локальных переменных.  При завершении работы

        память, занимаемая локальными переменными, освобождается. В любой

        момент  выполнения  программы общий размер локальных переменных в

        активных процедурах и функциях не должен превышать  размера  сег-

        мента стека.

 

                   Примечание: Если вы пишете приложение для Windows,  то

              Windows налагает на сегменты  данных  и  стека  специальные

              требования,  так  что рабочий максимум стека и область сег-

              мента данных могут быть меньше, чем упомянутые максимальные

              области сегмента данных и стека.

 

              Директива компилятора $S используется для проверок перепол-

        нения стека в программе.  В состоянии {$S+},  принятом по умолча-

        нию, генерируется код, осуществляющий проверку переполнения стека

        в начале каждой процедуры или функции.  В состоянии  {$S-}  такие

        проверки не проводятся.  Переполнение стека может вызвать аварий-

        ное завершение работы системы,  поэтому не следует отменять  про-

        верки стека,  если нет абсолютной уверенности в том, что перепол-

        нения не произойдет.

Абсолютные переменные

             Переменные можно описать так, что они будут располагаться по

        определенному адресу в памяти, и в этом случае они называются аб-

        солютными переменными. Описание таких переменных должно содержать

        после типа оператор absolute:

 

         описание       ЪДДДДДДДДї    ЪДДДДДДДДДї  ЪДДДї  ЪДДДДДДДДДї

         абсолютной ДДД>іabsoluteГДВД>іцелое безГД>і : ГД>іцелое безГДВД>

         переменной     АДДДДДДДДЩ і  і знака   і  АДДДЩ  і знака   і і

                                   і  АДДДДДДДДДЩ         АДДДДДДДДДЩ і

                                   і       ЪДДДДДДДДДДДДДї            і

                                   АДДДДДД>іидентификаторГДДДДДДДДДДДДЩ

                                           і  переменной і

                                           АДДДДДДДДДДДДДЩ

 

             Отметим, что список идентификаторов  в  описании  переменной

        при указании оператора absolute может содержать только один иден-

        тификатор.

 

             Первая часть оператора absolute содержит сегмент и смещение,

        то есть адрес, по которому переменная должна быть размещена.

 

             CrtMode   : byte absolute $0040:$0049;

 

             Первая константа обозначает базу сегмента,  а вторая опреде-

        ляет смещение внутри этого сегмента.  Обе константы не должны вы-

        ходить за пределы диапазона от $0000 до $FFFF (от 0 до 65535).

 

             В программах защищенного режима DOS и в Windows первую форму

        оператор absolute нужно использовать очень аккуратно, если вообще

        стоит это  делать.  Во  время  выполнения  прикладной   программы

        Windows или  DOS защищенного режима она может не иметь полномочий

        доступа к областям памяти вне вашей программы.  Попытка доступа к

        этим областям памяти может привести к сбою программы.

             Вторая форма  оператора  absolute  используется для описания

        переменной,  которая помещается "поверх"  другой  переменной,  то

        есть по тому же самому адресу, что и другая переменная.

 

             var

               Str: string[32];

               StrLen: byte absolute Str;

 

             Это описание указывает,  что переменная StrLen должна разме-

        щаться с того же адреса, что и переменная Str, а поскольку первый

        байт  строковой переменной содержит динамическую длину строки, то

        StrLen будет содержать длину Str.

 

             Эту вторую форму оператора absolute можно без  опасения  ис-

        пользовать при программировании в Windows или в защищенном режиме

        DOS. Память,  к которой вы обращаетесь, находится в области прог-

        раммы.

Ссылки на переменные

             Ссылка на переменную может обозначать следующее:

 

             - переменную;

 

             - компонент в переменной структурного или строкового типа;

 

             - динамическую переменную,  на которую указывает  переменная

               типa указатель.

 

             Синтаксис ссылки на переменную имеет вид:

 

                         ЪДДДДДДДДДДДДДї

         ссылка на  ДВДД>іидентификаторГДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДД>

         переменную  і   і  переменной і        ^^  ЪДДДДДДДДДДДДї  і

                     і   АДДДДДДДДДДДДДЩ        іАДДґквалификаторі<ДЩ

                     і   ЪДДДДДДДДДДДДДДДї      і   АДДДДДДДДДДДДЩ

                     ГДД>іприведение типаГДДДДДДґ

                     і   і  переменной   і      і

                     і   АДДДДДДДДДДДДДДДЩ      АДДДДДї

                     і   ЪДДДДДДДДДї  ЪДДДДДДДДДДДДї  і

                     АДД>івыражениеГД>іквалификаторГДДЩ

                         АДДДДДДДДДЩ  АДДДДДДДДДДДДЩ

 

             Отметим, что  синтаксис  ссылки  на переменную допускает ис-

        пользование выражения, вычисляющего значение ссылочного типа. Вы-

        ражение должно следовать за квалификатором, разыменовывающим ссы-

        лочное значение (или индексирующим значением  указателя,  если  с

        помощью директивы {$X+} разрешен расширенный синтаксис), что дает

        фактическую ссылку на переменную.

Квалификаторы

             Обращение к функции представляет собой  идентификатор  пере-

        менной с несколькими квалификаторами или без них, которые изменя-

        ют значение обращения к функции.

 

                                      ЪДДДДДДї

                   квалификатор ДДВДД>іиндексГДДДДДДДДДД>

                                  і   АДДДДДДЩ        ^

                                  і   ЪДДДДДДДДДДДДї  і

                                  ГДД>і десигнатор ГДДґ

                                  і   і    поля    і  і

                                  і   АДДДДДДДДДДДДЩ  і

                                  і   ЪДДДї           і

                                  АДД>і ^ ГДДДДДДДДДДДЩ

                                      АДДДЩ

 

             Идентификатор массива без квалификатора является  ссылкой на

        весь массив, например:

 

             Results

 

             Идентификатор массива  с указанным индексом обозначает конк-

        ретный элемент массива, в данном случае структурную переменную:

 

             Results[Current+1]

 

             В случае,  если элементом является запись, за индексом можно

        указать обозначение поля.  В этом случае ссылка на переменную оз-

        начает конкретное поле конкретного элемента массива:

 

             Results[Current+1].Data

 

             Десигнатор  поля в указателе-поле может сопровождаться  сим-

        волом указателя (^) с тем,  чтобы указать различие между указате-

        лем-полем и динамической переменной, на которую он указывает.

 

              Results[Current+1].Data^

 

             Если переменная,  на которую указывается, является массивом,

        то  можно добавить индексы для обозначения компонентов этого мас-

        сива.

 

              Results[Current+1].Data^[J]

Массивы, строки и индексы

             Конкретный элемент  массива обозначается с помощью ссылки на

        переменную массива,  за которой указывается индекс,  определяющий

        данный элемент.

 

             Конкретный символ  в строковой переменной обозначается с по-

        мощью ссылки на строковую переменную,  за которой указывается ин-

        декс, определяющий позицию символа.

 

                             ЪДДДї        ЪДДДДДДДДДї        ЪДДДї

                   индекс ДД>і [ ГДДДДДДД>івыражениеГДДДДВДД>і ] ГДД>

                             АДДДЩ  ^     АДДДДДДДДДЩ    і   АДДДЩ

                                    і       ЪДДДї        і

                                    АДДДДДДДґ , і<ДДДДДДДЩ

                                            АДДДЩ

 

             Индексные выражения обозначают компоненты  в соответствующей

        размерности  массива.  Число  выражений не должно превышать числа

        индексных типов в описании массива. Более того, тип каждого выра-

        жения  должен  быть совместимым по присваиванию с соответствующим

        индексным типом.

 

             В случае многомерного массива можно  использовать  несколько

        индексов или несколько выражений в индексе. Например:

 

             Matrix[I][J]

 

        что тождественно записи:

 

             Matrix[I,J]

 

             Строковую переменную  можно  проиндексировать с помощью оди-

        ночного индексного выражения, значение которого должно быть в ди-

        апазоне  0...n,  где n - указанный в описании размер строки.  Это

        дает доступ к каждому символу в строковом значении, если значение

        символа имеет тип Char.

 

             Первый символ строковой переменной (индекс 0) содержит дина-

        мическую длину строки,  то есть Length(S) тождественно Ord(S[0]).

        Если атрибуту длины присваивается значение, то компилятор не про-

        веряет, является ли это значение меньшим описанного размера стро-

        ки. Вы можете указать индекс строки и вне ее текущей динамической

        длины.  В этом случае считываемые  символы  будут  случайными,  а

        присваивания вне текущей длины не повлияют на действительное зна-

        чение строковой переменной.

 

             Когда с помощью директивы компилятора {$X+} разрешен  расши-

        ренный синтаксис,  значение PChar может индексироваться одиночным

        индексным выражением типа Word. Индексное выражение задает смеще-

        ние, которое  нужно  добавить  к символу перед его разыменованием

        для получения ссылки на переменную типа Char.

Записи и десигнаторы полей

             Конкретное поле  переменной-записи  обозначается  с  помощью

        ссылки на переменную-запись,  после которой указывается обозначе-

        ние поля, специфицирующее это поле.

 

                                  ЪДДДї    ЪДДДДДДДДДДДДДї

             обозначение поля ДДД>і . іДДД>іидентификаторіДДД>

                                  АДДДЩ    і поля        і

                                           АДДДДДДДДДДДДДЩ

 

             Приведем несколько примеров десигнаторов полей:

 

             Today.Year

             Results[1].Count

             Result[1].When.Month

 

             В операторе,  входящем в оператор with,  обозначению поля не

        должна предшествовать ссылка на переменную, содержащую запись.

Десигнаторы компонентов объекта

             Формат десигнатора  компонента  объекта совпадает с форматом

        десигнатора поля записи. То есть, он состоит из экземпляра (ссыл-

        ки на переменную),  за которым следует точка и идентификатор ком-

        понента. Десигнатор компонента, который обозначает метод, называ-

        ется  десигнатором  метода.  К  экземпляру  объектного типа можно

        применить оператор with.  В этом случае при ссылке на  компоненты

        объектного типа экземпляр и точку можно опустить.

 

             Экземпляр и точку можно опустить также в любом блоке метода.

        При этом эффект будет тот же,  что и при записи перед ссылкой  на

        компонент Self и точки.

Переменные-указатели и динамические переменные

             Значением переменной-указателя является  или  nil  (то  есть

        пустое значение), или адрес значения, указывающий на динамическую

        переменную.

 

             Ссылка на динамическую переменную,  на которую указывает пе-

        ременная-указатель,  записывается  в  виде  переменной-указателя,

        после которой ставится символ указателя (^).

 

             Динамические переменные и значения их указателей создаются с

        помощью стандартных процедур New и GetMem. Вы можете использовать

        операцию @ и стандартную функцию Ptr для создания значений указа-

        теля, которые рассматриваются как указатели динамических перемен-

        ных.

 

             Значение nil не указывает ни на какую  переменную.  Если  вы

        попытаетесь получить доступ к динамической переменной при неопре-

        деленном значении указателя или указателе,  равном nil, результат

        будет неопределенным.

 

             Приведем несколько  примеров  ссылок (указателей) на динами-

        ческие переменные:

 

             P1^

             P1.Sibling^

             Results[1].Data^

Приведение типов переменных

             Ссылка на  переменную одного типа может быть преобразована в

        ссылку на переменную другого типа с помощью приведения типов  пе-

        ременных.

 

                        ЪДДДДДДДДДДДДДї   ЪДДДї   ЪДДДДДДДДДДї   ЪДДДї

         приведение ДДД>іидентификаторГДД>і ( ГДД>іссылка на ГДД>і ) ГД>

         типов          і    типа     і   АДДДЩ   іпеременнуюі   АДДДЩ

                        АДДДДДДДДДДДДДЩ           АДДДДДДДДДДЩ

 

             Когда приведение типов применяется к ссылке  на  переменную,

        ссылка  на переменную рассматривается как экземпляр типа,  предс-

        тавленного идентификатором типа.  Размер переменной (число  байт,

        занимаемых переменной) должен быть равен размеру типа,  представ-

        ленного идентификатором типа.  После приведения  типа  переменной

        можно указать один или несколько квалификаторов,  если это допус-

        кается указанным типом.

 

                   Примечание: Определять  допустимость  приведения  типа

              должен программист.

 

             Приведем несколько примеров приведения типов переменных:

 

             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.

             Обратите внимание на использование для доступа к  младшим  и

        старшим байтам слова типа 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 }

 

             Обратите в частности внимание на операцию  получения  адреса

        @,  которая применяется к переменной процедурного типа.  Ее можно

        использовать в левой части  присваивания.  Кроме  того,  отметьте

        приведение  типа на последней строке при вызове функцию через пе-

        ременную-указатель.

Типизированные константы

             Типизированные константы можно сравнить с инициализированны-

        ми переменными - переменными,  значения которых  определяются  на

        входе в их блок.  В отличие от нетипизированных констант в описа-

        нии типизированной константы указывается как тип,  так и значение

        константы.

 

         описание типизированной константы

         і  ЪДДДДДДДДДДДДДї  ЪДДДї  ЪДДДї  ЪДДДї  ЪДДДДДДДДДДДДДДї

         АД>іидентификаторГД>і : ГД>ітипГД>і = ГД>ітипизированнаяГДД>

            АДДДДДДДДДДДДДЩ  АДДДЩ  АДДДЩ  АДДДЩ  і   константа  і

                                                  АДДДДДДДДДДДДДДЩ

 

         типизированная            ЪДДДДДДДДДДДДДДДДДДДї

         константа      ДДДДДДВДДД>і     константа     ГДДДДДДД>

                              і    АДДДДДДДДДДДДДДДДДДДЩ   ^

                              і    ЪДДДДДДДДДДДДДДДДДДДї   і

                              ГДДД>і адресная константаГДДДґ

                              і    АДДДДДДДДДДДДДДДДДДДЩ   і

                              і    ЪДДДДДДДДДДДДДДДДДДДї   і

                              ГДДД>і константа-массив  ГДДДґ

                              і    АДДДДДДДДДДДДДДДДДДДЩ   і

                              і    ЪДДДДДДДДДДДДДДДДДДї    і

                              ГДДД>і константа-запись ГДДДДґ

                              і    АДДДДДДДДДДДДДДДДДДЩ    і

                              і    ЪДДДДДДДДДДДДДДДДДДДї   і

                              ГДДД>і константа-объект  ГДДДґ

                              і    АДДДДДДДДДДДДДДДДДДДЩ   і

                              і    ЪДДДДДДДДДДДДДДДДДДДї   і

                              АДДД>іконстанта-множествоГДДДЩ

                                   АДДДДДДДДДДДДДДДДДДДЩ

 

             Типизированные константы можно использовать  точно  так  же,

        как  переменные  того  же самого типа,  и они указываются в левой

        части оператора присваивания.  Отметим,  что типизированные конс-

        танты  инициализируются  только  один  раз  - в начале выполнения

        программы.  Таким образом, при каждом новом входе в процедуру или

        функцию  локально  описанные  типизированные  константы заново не

        инициализируются.

 

             Кроме обычных   выражений-констант  значение  типизированной

        константы может задаваться с помощью адресного выражения-констан-

        ты. Адресное выражение-константа - это выражение, предусматриваю-

        щее получение адреса,  смещения или сегмента глобальной  перемен-

        ной, типизированной  константы,  процедуры или функции.  Адресные

        выражения-константы не могут ссылаться  на  локальные  переменные

        (расположенные в  стеке) или динамические переменные (размещенные

        в динамически распределяемой области памяти), поскольку их адреса

        нельзя вычислить на этапе компиляции.

Константы простого типа

             Описание типизированной  константы  с простым типом означает

        указание значения константы:

 

             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';

Константы структурного типа

             Описание константы  структурного  типа  определяет  значение

        каждого компонента структуры.  Borland Pascal поддерживает описа-

        ния констант типа массив, запись, множество и указатель. Констан-

        ты файлового типа и константы типа массив или запись,  содержащие

        компоненты файлового типа, не допускаются.

Константы типа массив

             Описание константы  типа массив содержит значения элементов,

        заключенные в скобки и разделенные запятыми.

 

                                  ЪДДДї     ЪДДДДДДДДДДДДДДї     ЪДДДї

            константа-массив  ДДД>і ( ГДДДД>ітипизированнаяГДДВД>і ) ГДД>

                                  АДДДЩ  ^  і   константа  і  і  АДДДЩ

                                         і  АДДДДДДДДДДДДДДЩ  і

                                         і      ЪДДДї         і

                                         АДДДДДДґ , і<ДДДДДДДДЩ

                                                АДДДЩ

 

             Приведем пример константы типа массив:

 

             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';

             В таких случаях оставшиеся символы  устанавливаются  в  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

Константы типа запись

             Описание константы типа запись содержит идентификатор и зна-

        чение каждого поля,  заключенные в скобки и разделенные точками с

        запятой.

 

         константа-запись

         і  ЪДДДї    ЪДДДДДДДДДДДДДї  ЪДДДї  ЪДДДДДДДДДДДДДДї    ЪДДДї

         АД>і ( ГДДД>іидентификаторГД>і : ГД>ітипизированнаяГДВД>і ) ГД>

            АДДДЩ ^  і     поля    і  АДДДЩ  і   константа  і і  АДДДЩ

                  і  АДДДДДДДДДДДДДЩ         АДДДДДДДДДДДДДДЩ і

                  і                   ЪДДДї                   і

                  АДДДДДДДДДДДДДДДДДДДґ ; і<ДДДДДДДДДДДДДДДДДДЩ

                                      АДДДЩ

 

             Приведем несколько примеров констант-записей:

 

             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);

 

             Поля должны указываться в том же порядке,  как они следуют в

        описании типа запись.  Если запись содержит поля файлового  типа,

        то  для  этого типа запись нельзя описать константу.  Если запись

        содержит вариант, то можно указывать только поля выбранного вари-

        анта. Если вариант содержит поле признака, то его значение должно

        быть определено.

Константы объектного типа

             При описании  константы  объектного типа используется тот же

        синтаксис, что и при описании константы типа запись. Значения для

        элементов (компонентов) метода задаваться не могут. С учетом при-

        водимых ранее описаний объектных типов, приведем некоторые приме-

        ры констант объектного типа:

 

             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);

 

             Константы объектного типа,  которые содержат виртуальные ме-

        тоды,  не требуется инициализировать с помощью вызова конструкто-

        ра. Эта инициализация автоматически выполняется компилятором.

Константы множественного типа

             Описание константы множественного типа может содержать  нес-

        колько  элементов,  заключенных в квадратные скобки и разделенных

        запятыми. Каждый элемент такой константы представляет собой конс-

        танту или отрезок типа,  состоящий из двух констант,  разделенных

        двумя точками.

 

                               ЪДДДї                               ЪДДДї

         константа-множество Д>і [ ГДВДДДДДДДДДДДДДДДДДДДДДДДДДДДД>і ] Г>

                               АДДДЩ і    ЪДДДДДДДДДДДДДДДДДї   ^  АДДДЩ

                                     АДДД>іконстанта-элементГДВДЩ

                                       ^  АДДДДДДДДДДДДДДДДДЩ і

                                       і        ЪДДДї         і

                                       АДДДДДДДДґ , і<ДДДДДДДДЩ

                                                АДДДЩ

 

                                ЪДДДДДДДДДї

         константа-элемент ДДДД>іконстантаГДДВДДДДДДДДДДДДДДДДДДДДДДДДД>

                                АДДДДДДДДДЩ  і  ЪДДї   ЪДДДДДДДДДї  ^

                                             АД>і..ГДД>іконстантаГДДЩ

                                                АДДЩ   АДДДДДДДДДЩ

 

             Приведем несколько примеров констант-множеств:

 

             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'];

Константы ссылочного типа

             Описание константы  ссылочного  типа  может содержать только

        значение 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 "Строки с завершаю-

        щим нулем".

Константы процедурного типа

             Константы процедурного  типа должны определять идентификатор

        процедуры или функции,  совместимый по присваиванию с типом конс-

        танты.

 

                                          ЪДДДДДДДДДДДДДДДДДї

         процедурная константа ДДДДДДВДДД>іконстанта-элементГДДДДДДДДДДД>

                                     і    АДДДДДДДДДДДДДДДДДЩ   ^

                                     і    ЪДДДДДДДДДДДДДДДДДї   і

                                     ГДДД>іконстанта-элементГДДДґ

                                     і    АДДДДДДДДДДДДДДДДДЩ   і

                                     і          ЪДДДї           і

                                     АДДДДДДДДД>іnilГДДДДДДДДДДДЩ

                                                АДДДЩ

 

             Приведем следующий пример:

 

             type

                ErrorProc = procedure(ErrorCode: Integer);

 

             procedure DefaultError(ErrorCode: Integer); far;

             begin

                  WriteLn('Error ', ErrorCode, '.');

             end;

 

             const

                  ErrorHandler: ErrorProc = DefaultError;