При описании переменной необходимо указать ее тип. Тип переменной описывает набор значений,  которые она может принимать,  и  действия, которые могут быть над ней выполнены. Описание типа определяет идентификатор, который обозначает этот тип.

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

  описание ДД>і идентификатор ГДД>і = ГДД>і тип ГДД>і ; ГДД>

  типа   АДДДДДДДДДДДДДДДЩ  АДДДЩ   АДДДДДЩ   АДДДЩ

Указание идентификатора  в левой части описания типа означает, что он определен как идентификатор типа для блока, в котором  указано  это описание типа. Область действия идентификатора типа  не включает его самого,  исключение составляют  типы "указатель"  (которые называют также ссылочными типами).

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

   тип   ДДДДДДДДВДДДД>і простой тип іДДДДДДДДД>

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

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

  ГДДДД>і   строковый тип ГДДДДґ

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

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

  ГДДДД>і   ссылочный тип ГДДДДґ

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

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

  ГДДДД>і   структурный тип  ГДДДДґ

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

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

  ГДДДД>і   процедурный тип  ГДДДДґ

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

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

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

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

Имеется пять следующих основных классов типов.  Они описываются в следующем разделе.

Простые типы определяют упорядоченные множества значений.

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

простой тип ДДДДДВДДДД>і  порядковый тип   ГДДДДДДДДД>

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

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

АДДДД>і вещественный тип  ГДДДДДЩ

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

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

вещественный тип ДДДДД>і   идентификатор ГДДДДД>

і вещественного типа і

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

Идентификатор вещественного типа относится к числу стандартных идентификаторов,  которые могут быть вещественными, с одинарной точностью,  с  двойной точностью,  с повышенной точностью и  сложными.

Примечание: В разделах "Числа" и "Строковые константы"  Главы 2 вы можете найти описание того, как обозначать константы целого и вещественного типов.

Порядковые типы  представляют собой подмножество простых типов. Все простые типы,  отличные от вещественных типов, являются  порядковыми и выделяются по следующим четырем характеристикам.

-  Все возможные значения данного порядкового типа представляют собой упорядоченное множество,  и  каждое  возможное значение связано с порядковым номером,  который представляет собой целочисленное значение.  За исключением значений целочисленного типа,  первое значение любого порядкового типа имеет порядковый номер  0,  следующее  значение имеет порядковый номер 1 и так далее для каждого значения в этом порядковом типе. Порядковым номером значения целочисленного  типа является само это значение.  В любом порядковом типе каждому значению,  кроме первого, предшествует  другое  значение,  и после каждого значения,  кроме последнего, следует другое значение в соответствии с упорядоченностью типа.

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

-  К  любому значению порядкового типа можно применить стандартную функцию Pred,  возвращающую  предшествующее этому значению значение. Если эта функция применяется к первому  значению в этом порядковом типе, то выдается сообщение об ошибке.

-  К  любому значению порядкового типа можно применить стандартную функцию Succ, возвращающую следующее за этим значением значение. Если эта функция применяется к последне-му значению в этом порядковом типе, то выдается сообщение об ошибке.

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

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

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

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

   порядковый  ДДДДДВДДДД>і   отрезок типа  ГДДДДДДДДД>

   тип   і АДДДДДДДДДДДДДДДДДДДДЩ  ^

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

   ГДДДД>і  перечислимый тип  ГДДДДДґ

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

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

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

   і порядкового типа   і

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

Borland Pascal имеет 10 встроенных порядковых типов: Integer (целое), Shortint (короткое целое), Longint (длинное целое), Byte  (длиной в байт),  Word (длиной  в  слово),  Boolean (булевское),  ByteBool (булевское размером в байт),  WordBool (булевское размером в слово), LongBool (длинный булевский тип) и Char (символьный  тип). Кроме того, имеется два других класса определяемых пользователем порядковых типов: перечислимые типы и отрезки типов (поддиапазоны).

В Borland Pascal имеется пять предопределенных целочисленных   типов: Shortint (короткое целое), Integer (целое), Longint (длинное целое),  Byte (длиной в байт) и Word (длиной в слово). Каждый  тип обозначает определенное подмножество целых чисел, как это показано в следующей таблице.

  Предопределенные целочисленные типы Таблица 4.1

  ЪДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДї

  і  Тип   і   Диапазон   і   Формат   і

  ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДґ

  і  короткое целое   і -128 .. 127  і   8 бит со знаком   і

  і   (Shortint) і  і   і 

  ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДґ 

  і   целое   і  -32768 .. 32767   і   16 бит со знаком  і

  і   (Integer)  і  і   і 

  ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДґ 

  і   длинное целое і  -2147483648 .. і   32 бита со знаком і

  і   (Longint)  і ..2147483647 і   і 

  ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДґ 

  і   длиной в байт і0 .. 255  і  8 бит  без знака  і

  і  (Byte)  і  і   і

  ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДґ

  і  длиной в слово   і 0 .. 65535   і   16 бит без знака  і

  і   (Word)  і  і   і 

  АДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДЩ

Арифметические действия  над операндами целочисленного типа  предполагают 8-битовую,  16-битовую и 32-битовую точность в соответствии со следующими правилами:

- Тип целой константы представляет собой встроенный целочисленный тип с наименьшим  диапазоном, включающим  значение  этой целой константы.

- В  случае  бинарной  операции (операции,  использующей два   операнда), оба операнда преобразуются к их общему типу перед  тем,  как над ними совершается действие.  Общим типом   является встроенный целочисленный тип с наименьшим  диапазоном, включающим все возможные значения обоих типов. Например, общим типом для целого и целого длиной в байт является  целое,  а  общим типом для целого и целого длиной в   слово является длинное целое. Действие выполняется в соответствии  с точностью общего типа и типом результата является общий тип.

- Выражение справа в операторе присваивания вычисляется  независимо от размера или типа переменной слева.

- Любые операнды размером в байт преобразуются к промежуточному операнду размером в слово,  который  совместим перед   выполнением  арифметической  операции  с  типами Integer и   Word.

Значение одного целочисленного типа может быть явным образом преобразовано  к другому целочисленному типу с помощью приведения  типов.

Примечание: Приведение типов описывается в Главах 5 и 6.

Существует 4  предопределенных  булевских   типа:   Boolean,  ByteBool, WordBool иLongBool. Значения булевского типа обозначаются встроенными идентификаторами констант False и True. Поскольку булевский  тип является перечислимым,  между этими значениями  имеют место следующие отношения:

- False < True

- Ord(False)  = 0

- Ord(True)   = 1

- Succ(False) = True

- Pred(True)  = False

Переменные типа Boolean иByteBool  занимают 1 байт,   переменная WordBool занимает два байта (слово), а переменная LongBool занимает четыре байта (два слова). Boolean - это наиболее предпочтительный тип,   использующей   меньше  памяти;  типа ByteBool,  WordBool и LongBool обеспечивают совместимость с другими  языками  и средой Windows.

Предполагается, что переменная типа Boolean имеет порядковые  значения 0 и 1,  но переменные типа ByteBool, WordBool и LongBool  могут иметь  другие  порядковые  значения. Когда  выражение типа  ByteBool, WordBool или LongBool равна 1,  то подразумевается, что она имеет  значение  True, а если оно равно 0 - то False. Когда  значение типа ByteBool, WordBool или LongBool используется в контексте, где ожидается значение Boolean,  компилятор будет автоматически генерировать код,  преобразующий любое ненулевое значение  в значение True.

Множеством значений этого типа являются символы, упорядоченные в соответствии с расширенным набором символов кода ASCII. При  вызове функции Ord(Ch), где Ch - значение символьного типа, возвращается порядковый номер Ch.

Строковая константа  с длиной  1  может обозначать значение  константы символьного типа. Любое значение символьного типа может  быть получено с помощью стандартной функции Chr.

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

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

перечислимый ДД>і ( ГДДД>і   список   ГДДД>і ) ГДДД>

тип    АДДДЩ іидентификаторові АДДДЩ

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

список ЪДДДДДДДДДДДДДї

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

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

і   ЪДДДї   і

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

АДДДЩ

При указании идентификатора в списке  идентификаторов  перечислимого типа он описывается как константа для блока,  в котором  указано описание перечислимого типа. Типом этой константы является описанный перечислимый тип.

Порядковый номер  перечислимой константы определяется ее позицией в списке идентификаторов при описании. Перечислимый тип, в  котором описывается константа,  становится ее типом. Первая перечислимая константа в списке имеет порядковый номер 0.

Приведем пример перечислимого типа:

type

suit = (club, diamond, heart, spade);

Согласно этим  описаниям diamond  является  константой типа  suit.

При применении функции Ord к значению перечислимого типа Ord  возвращает целое число, которое показывает, какое положение занимает это значение в отношении других значений этого перечислимого  типа. Согласно предшествующим описаниям, Ord(club) возвращает 0,  Ord(diamond) возвращает 1 и так далее.

Отрезок типа представляет собой диапазон значений из  порядкового типа,  называемого главным типом. Определение отрезка типа  включает наименьшее и наибольшее  значение в  поддиапазоне.  Оно  имеет следующий синтаксис:

   отрезок ЪДДДДДДДДДДДїЪДДДДї ЪДДДДДДДДДДДї

   типа ДДДДДДДДДДД>і константа ГДДД>і .. ГДДД>і константа ГДДД>

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

Обе константы должны иметь один и тот же порядковый тип. Отрезки типов,  имеющие вид a..b,  предполагают,  что a меньше или  равно b.

Приведем примеры отрезков типов:

0..99

-128..127

club..heart

Переменная отрезка типа имеет все свойства переменных  главного типа,  однако ее значение на этапе выполнения должно принадлежать указанному интервалу.

Разрешение использования выражений-констант там,  где  стандартный Паскаль  допускает только простые константы, приводит к  некоторой синтаксической  неоднозначности.  Рассмотрим  следующие описания:

 

const

X = 50;

Y = 10;

type

Color = (Red, Green, Blue);

Scale = (X - Y) * 2..(X + Y) * 2;

Согласно синтаксису стандартного Паскаля,  если  определение  типа начинается с круглой скобки,  то это перечислимый тип (такой  как Color в данном примере).  Однако Scale предназначен для определения отрезка типа.  Решение состоит в том,  чтобы переупорядочить первое выражение поддиапазона или задать  другую  константу,  равную значению данного выражения, и использовать эту константу в  определении типа:

   type

   Scale = 2 * (X - Y)..(X + Y);

К вещественному типу относится подмножество вещественных чисел, которые могут быть представлены в формате с плавающей точкой  с фиксированным числом цифр.  Запись значения в формате с плавающей запятой обычно включает три значения - m, b и e - таким образом, что m x b^e=n, где b всегда равен 2, а m и e являются целочисленными  значениями  в  диапазоне вещественного   типа.   Эти  значения m и e далее определяют диапазон представления и точность  вещественного типа.

Имеется пять видов вещественных типов:  вещественное (Real),  с одинарной точностью (Single),  с двойной точностью (Double),  с  повышенной точностью (Extended) и сложное  (Comp).  Действия над  типами с одинарной точностью,  с двойной точностью и с повышенной  точностью и над сложным типом могут выполняться только при  наличии числового сопроцессора 8087 (который был описан ранее).

Вещественные типы различаются диапазоном и точностью связанных с ними значений (см. Таблицу 4.2).

  Диапазон представления

  и десятичные цифры для вещественных типов   Таблица 4.2

  ЪДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДї

  і  Тип  і  Диапазон  і  Цифры   і

  ГДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДґ

  і вещественное і2.9x10^-39 .. 1.7x10^38 іот 11 до 12і

  і (Real) і  і  і

  ГДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДґ

  і с одинарной точностью і1.5x10^-45 .. 3.4x10^38 іот 7 до 8  і

  і (Single)  і   і  і

  ГДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДґ

  і с двойной точностью   і5.0x10^-324 .. 1.7x10^308  іот 15 до 16і

  і (Double)  і   і  і

  ГДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДґ

  і с повышенной точностьюі1.9x10^-4951 .. 1.1x10^4932іот 19 до 20і

  і (Extended)   і   і  і

  ГДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДґ

  і сложный тип і   -2^63 + 1 .. 2^63 - 1   і і

  і (Comp) і   і  і

  АДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДЩ

Примечание: Сложный тип содержит только  целочисленные  значения  в диапазоне от -2^63+1 до 2^63-1, что приблизительно равно -9.2x10^18 и 9.2x10^18.

Borland Pascal поддерживает две модели  генерации  кода для  выполнения действий над вещественными типами: программную для чисел с плавающей точкой и аппаратную для чисел с плавающей точкой. Выбор соответствующей  модели осуществляется с помощью директивы  компилятора $N.

В состоянии {$N-}, которое устанавливается по умолчанию, генерируемый код выполняет все вычисления  с  вещественными  типами  программно, через вызов подпрограмм библиотеки исполняющей системы. Из-за соображений скорости и размера кода в  этом  состоянии  допускаются только действия над переменными типа real (вещественное). Любая попытка оттранслировать операторы, выполняющие действия над типами с одинарной точностью, с двойной точностью, с повышенной точностью и над сложными типами,  вызовет  сообщение об ошибке.

В состоянии {$N+} генерируемый  код выполняет все вычисления  над вещественными типами с помощью числового  сопроцессора  8087.  Это состояние позволяет использовать все пять вещественных типов,  однако оно требует наличия сопроцессора 8087 на  этапе компиляции  и выполнения.

Borland Pascal включает в себя библиотеки исполняющей системы, которые автоматически эмулируют программным путем сопроцессор  80х87, если при выполнении прикладной программы DOS реального или  защищенного режима он отсутствует.  Для определения того, следует  ли в программу DOS включить эмулятор сопроцессора 80x87,  используется директива компилятора $E. Если вы создает прикладную программу для  реального  или  защищенного режима DOS,  и сопроцессор  80х87 отсутствует,  разрешение директивы компилятора $E обеспечивает полную программную эмуляцию сопроцессора 80x87. Для программ  Windows директива $E не действует,  так как Windows  обеспечивает  собственные подпрограммы эмуляции.

Примечание: Более  детальное описание  генерации кода  при аппаратной поддержке чисел с плавающей запятой вы можете  найти  в  Главе 15  "Использование сопроцессора 8087 в  Borland Pascal".

Значением строкового типа является последовательность символов с динамическим атрибутом длины (в зависимости от действительного числа символов при выполнении программы) и постоянным  атрибутом размера в диапазоне от 1 до 255.  Текущее значение атрибута  длины можно получить с помощью стандартной функции Length.

  ЪДДДДДДї

  строковый тип ДДД>іstringГДДВД>

  АДДДДДДЩ  і  ^

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

   АД>і [ ГДД>іцелоеГДД>і ] ГДЩ

  АДДДЩ   і без і   АДДДЩ

  ізнакаі

  АДДДДДЩ

Примечание: Операторы работы со строковыми типами описываются разделах  "Строковые операторы" и "Операторы отношений" Главы 6.

Отношение между  любыми двумя строковыми значениями устанавливается согласно отношению порядка между значениями  символов  в  соответствующих позициях. В двух строках разной длины каждый символ более длинной строки без соответствующего символа в более короткой строке принимает значение "больше"; например, 'Xs' больше,  чем 'X'.  Нулевые строки могут быть равны только  другим  нулевым  строкам, и они являются наименьшими строковыми значениями.

Примечание: Стандартные процедуры и функции для работы  со строковыми типами описаны в разделе "Строковые процедуры  и функции".

К символам в строках можно обращаться как к элементам массива. См. раздел "Массивы, строки и индексы" в Главе 5.

К идентификатору  строкового типа  и к ссылке на переменную  строкового типа можно применять стандартные функции Low и High. В  этом случае  функция Low возвращает 0, а High возвращает атрибут  размера (максимальную длину) данной строки.

Параметр-переменная, описанная  с   помощью   идентификатора  OpenString и  ключевого слова string в состоянии {$P+},  является  открытым строковым параметром.  Открытые строковые параметры позволяют  передавать одной и той же процедуре или функции строковые  переменные изменяющегося размера.

Примечание: Открытые строковые параметры описываются в  Главе 9.

Структурный тип,  характеризуемый методом структурирования и  типами своих компонентов,  имеет более одного значения.  Если тип  компонента  является  структурным,  то получаемый  в  результате  структурный  тип  имеет  более одного  уровня  структурирования.  Структурный  тип может иметь неограниченные уровни структурирования.

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

структурный ДДВДДДДДДДДДДДДДДДДВДД>і  тип массив   ГДДДДД>

тип і  ЪДДДДДДДДї ^  і  АДДДДДДДДДДДДДДДЩ  ^

АД>і packed ГДЩ  і  ЪДДДДДДДДДДДДДДДї  і

АДДДДДДДДЩ ГДД>і множественный ГДДґ

і   і тип і  і

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

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

ГДД>і файловый тип  ГДДґ

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

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

ГДД>і тип "запись" ГДДґ

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

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

АДД>і объектный тип ГДДЩ

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

Слово packed (упакованный) в описании структурного типа требует от  компилятора  уплотнить хранимые  данные,  даже за счет  уменьшения скорости доступа к компоненту в переменной этого типа.  Слово packed  не  имеет никакого действия в Borland Pascal,  поскольку упаковка выполняется здесь автоматически  всюду,  где это  возможно.

Массивы содержат фиксированное число элементов одного  типа,  так называемого типа элемента.  На приводимой ниже синтаксической  диаграмме тип элемента следует за словом of.

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

  тип ДД>і array ГД>і [ ГДДД>і тип  ГДВД>і ] ГД>і of ГД>і тип Г>

  массив  АДДДДДДДЩ  АДДДЩ ^  іиндексаі і АДДДЩ  АДДДДЩ  АДДДДДЩ

  і АДДДДДДДЩ і

  і ЪДДДї  і

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

  АДДДЩ

тип   ЪДДДДДДДДДДДДДДДДї

индекса ДДД>і порядковый тип ГДДД>

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

В индексных типах, по одному для каждой размерности массива,  указывается число элементов.  Допустимыми индексными типами являются все порядковые типы, за исключением длинного целого и поддиапазонов  длинного  целого.  Массив может быть проиндексирован по  каждой размерности всеми значениями  соответствующего  индексного  типа; число  элементов поэтому равно числу значений в каждом индексном типе. Число размерностей не ограничено.

Приведем пример типа массив:

array[1..100] of Real

Если тип элемента в типе массив также является  массивом, то  результат  можно  рассматривать  как массив массивов или как один  многомерный массив. Например,

array[boolean] of array[1..100] of array[Size] of Real

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

array[boolean,1..10,Size] of Real

    Кроме того, можно записать выражение:

packed array[1..10] of packed array[1..8] of Boolean

  как

packed array[1..10,1..8] of Boolean

Для доступа к элементам массива необходимо указать идентификатор  массива  с одним или несколькими индексами в скобках (см.  раздел "Массивы, строки и индексы").

Тип массив, имеющий вид:

packed array[M..N] of Char

где M меньше N,  называется упакованным  строковым типом  (слово  packed  можно  опустить,  поскольку оно  не оказывает действия в  Borland Pascal). Упакованный строковый тип имеет некоторые свойства, не характерные для других типов массив (см. раздел "Тождественные и совместимые типы" далее в этой главе).

Массив вида:

array[0..X] of Char

где X - положительное целое число,  называется массивом с нулевой  базой. Массивы  с нулевой базой используются для хранения строк с  завершающим нулем, и, когда разрешен расширенный синтаксис (с помощью директивы  компилятора {$X+}),  символьный массив с нулевой  базой совместим со значением типа PChar.  Полностью эта тема  обсуждается в Главе 18 "Использование строк с завершающим нулем".

Параметр, описанный с помощью синтаксиса array of T, называется открытым строковым параметром.  Открытые строковые параметры  позволяют передавать одной и той же процедуре или функции строковые переменные изменяющегося размера.

Примечание: Открытые строковые параметры описываются в  Главе 9.

Тип запись содержит установленное число элементов или полей,  которые могут быть различных типов. Описание типа запись указывает тип каждого поля и идентификатор, который именует поле.

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

   тип запись ДДД>і record ГДДВДДДДДДДДДДДДДДДД>і end ГДД>

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

   АД>і список ГДЩ

   і  полей і

  АДДДДДДДДЩ

 

   список  ЪДДДДДДДДДДДДї

   полейВД>і фиксирован-ГДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДД>

  і  і ная часть  і і  ЪДДДїЪДДДДДДДДДДДДї ^ і  ЪДДДї ^

  і  АДДДДДДДДДДДДЩ АД>і ; ГДДД>і вариантная ГДЩ АД>і ; ГДЩ

  і  АДДДЩ ^ і   часть і  АДДДЩ

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

 

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

  фиксированная ДДДД>і  список   ГДД>і : ГДДД>і тип ГДДВДД>

  часть  ^  і идентификаторов і   АДДДЩ АДДДДДЩ і

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

   і   і

   і   ЪДДДї і

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

   АДДДЩ

Фиксированная часть типа запись содержит список  фиксированных полей вместе с идентификатором и типом для каждого поля. Каждое поле содержит информацию, которая всегда отыскивается одним и тем же способом.

Приведем пример типа запись:

record

   year:  integer; { год }

   month: 1..12;   { месяц }

   day:   1..31;   { число }

end

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

   вариантная часть

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

  АД>іcaseГДВДДДДДДДДДДДДДДДДДДД>ітип поляГД>іofГДДДД>івариантГДВ>

   АДДДДЩ і  ^ іпризнакаі  АДДЩ ^   АДДДДДДДЩ і

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

А>іиденти-Г>і : ГДЩ АДДДДґ ; і<ДДДЩ

   іфикаторі АДДДЩ  АДДДЩ

   АДДДДДДДЩ

 

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

   тип поля ДДДД>і  идентификатор ГДДДД>

   признака   іпорядкового типаі

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

 

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

   вариант ДДДД>іконстантаГДВД>і : ГД>і ( ГДВДДДДДДДДДДДДД>і ) ГДД>

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

і ЪДДДї  і   і  і

АДДДДґ , і<ДДДДЩ   і  ЪДДДДДДї і

   АДДДЩ   АД>ісписокГДЩ

 іполей і

 АДДДДДДЩ

Вы можете видеть на диаграмме,  что каждый вариант идентифицирован  по  крайней мере одной константой.  Все константы должны  быть отличными друг от друга и иметь порядковый  тип, совместимый  с типом поля признака.  Доступ к вариантным и фиксированным полям  один и тот же.

В вариантной части можно указать необязательный  идентификатор -  идентификатор  признака поля.  При наличии идентификатора  признака поля он становится идентификатором дополнительного  фиксированного поля записи - поля признака.  Программа может использовать значение поля признака для указания, какой вариант является активным  в  настоящий момент.  Без  указания поля признака  программа выбирает вариант по другому критерию.

Ниже приводятся несколько примеров типов запись:

record

   firstName,lastName : string[40];

   birthDate : Date;

   case citizen : boolean of

  True  : (birthPlace: string[40]);

  False : (country   : string[20];

  entryPort : string[20];

  entryDate : Date;

  exitDate  : Date);

end

 

record

   x,y : real;

   case kind : Figure of

  rectangle : (height,wigth: real);  { прямоугольник }

  triangle : (size1,side2,angle: real); { треугольник }

  circle : (radius: real);  { круг }

end

Объектный тип является структурой,  состоящей из фиксированного числа компонентов. Каждый компонент является либо полем, содержащим данные строго определенного типа, либо методом, выполняющим операции над объектом.  По аналогии с описанием переменных,  описание поля указывает тип данного этого поля  и  идентификатор,  именующий  поле:  по  аналогии с описанием процедуры или функции,  описание метода указывает заголовок процедуры, функции, конструктора или деструктора.

Объектный тип может наследовать компоненты другого объектного типа.  Если T2 наследует от T1,  то T2 является потомком T1, а  T1 является родителем T2.

Наследование является транзитивным, то есть если T3 наследует от T2,  а T2 наследует от T1,  то T3 наследует от T1.  Область  (домен) объектного типа состоит из него самого и из всех его наследников.

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

   тип объектаДД>іobjectГДВДДДДДДДДДДДДДДДДДДД>ісписок компонентГДї

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

 АД>іHаследованиеГДЩ   і

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

    ЪДДДДДДДДДДДДДДЩ

і  ЪДДДї

АДВДДДДДВДґendГ>

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

  АДД>іprivateГДД>ісписок компонентГДЩ

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

 

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

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

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

 

   список компонент ДДВДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДД>

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

АД>і список ГДДЩ  АД>і список  ГДДЩ

і полей  і і методов і

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

 

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

   список полей ДДД>іcписок идентификаторовГД>і : ГД>іtypeГ>і ; ГВ>

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

  і і

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

 

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

   список методов ДД>ізаголовокГДВДДДДДДДДДДДДДДДДДДДДДДДДДДґ ; ГВД>

   ^  і метода і і ЪДДДї  ЪДДДДДДДї  ^АДДДЩі

   і  АДДДДДДДДДЩ А>і ; ГД>іvirtualГВДДДДДДДЩ  і

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

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

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

   і  А>і  целая ГЩі

   і іконстантаі і

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

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

 

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

   заголовок метода ДДДДВДДД>і заголовок процедуры ГДДДДДД>

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

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

   ГДДД>і заголовок функции   ГДДґ

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

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

   ГДДД>і заголовок конструктора ГДДґ

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

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

   АДДД>і заголовок деструктора  ГДДЩ

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

Следующий исходный  код приводит пример описания объектного  типа. Далее во всей этой главе на данное описание будут делаться  ссылки.

type

   Point = object

   X, Y: integer;

end;

 

Rect = object

   A, B: TPoint;

   procedure Init(XA, YA, XB, YB: Integer);

   procedure Copy(var R: TRectangle);

   procedure Move(DX, DY: Integer);

   procedure Grow(DX, DY: Integer);

   procedure Intersect(var R: TRectangle);

   procedure Union(var R: TRectangle);

   function Contains(P: Point): Boolean;

end;

 

StringPtr = ^String;

FieldPtr = ^TField;

 

TField = object

   X, Y, Len: Integer;

   Name: StringPtr;

   constructor Copy(var F: TField);

   constructor Init(FX, FY, FLen: Integer; FName: String);

   destructor Done; virtual;

   procedure Display; virtual;

   procedure Edit; virtual;

   function GetStr: String; virtual;

   function PutStr(S: String): Boolean; virtual;

end;

 

StrFieldPtr = ^TStrField;

 

StrField = object(TField)

   Value: PString;

   constructor Init(FX, FY, FLen: Integer; FName: String);

   destructor Done; virtual;

   function GetStr: String; virtual;

   function PutStr(S: String): Boolean;

   virtual;

   function Get: string;

   procedure Put(S: String);

end;

NumFieldPtr = ^TNumField;

 

TNumField = object(TField)

private

   Value, Min, Max: Longint;

    public

   constructor Init(FX, FY, FLen: Integer; FName: String;

  FMin, FMax: Longint);

function GetStr: String; virtual;

function PutStr(S: String): Boolean; virtual;

    function Get: Longint;

function Put(N: Longint);

end;

 

ZipFieldPtr = ^TZipField;

 

ZipField = object(TNumField)

function GetStr: String; virtual;

function PutStr(S: String): Boolean;

virtual;

end;

В отличие от других типов,  объектные типы могут описываться  только  в  разделе  описаний типов,  находящемся на самом внешнем  уровне области действия программы или модуля. Таким образом, объектные  типы  не  могут описываться в разделе описаний переменных  или внутри блока процедуры, функции или метода.

Тип компоненты  файлового типа не может иметь объектный тип или любой структурный тип, содержащий компоненты объектного типа.

Область действия идентификатора компоненты  простирается  за  пределы объектного типа. Более того, область действия идентификатора компонента  простирается  сквозь  блоки  процедур, функций,  конструкторов и деструкторов, которые реализуют методы объектного  типа и его наследников.  Исходя из этих  соображений,  написание  идентификатора компоненты должно быть уникальным внутри объектного типа и внутри всех его наследников,  а также внутри  всех его  методов.

Область действия  идентификатора  компонента,  описанного  в  части private описания типа, ограничивается модулем (программой),  которая содержит описание объектного типа. Другими словами, частные (private) компоненты-идентификаторы действуют,  как  обычные  общедоступные  идентификаторы  в рамках модуля,  который содержит  описание объектного типа, а вне модуля любые частные компоненты и  идентификаторы  неизвестны и недоступны.  Поместив в один модуль  связанные типы объектов,  можно сделать так, что эти объекты смогут обращаться  к частным компонентам друг друга,  и эти частные  компоненты будут неизвестны другим модулям.

В описании объектного типа заголовок метода  может  задавать  параметры описываемого объектного типа, даже если описание еще не  полное. Это иллюстрируется методами Copy,  Intersect и Union типа  TRectange в предыдущем примере.

Описание метода  внутри объектного типа соответствует опережающему описанию метода (forward). Таким образом, где-нибудь после описания объектного типа, но внутри той же самой области действия, что и область действия описания объектного типа, метод должен реализоваться путем определения его описания.

Если требуется уникальный идентификатор метода, то используется уточненный идентификатор метода. Он состоит из идентификатора типа объекта, за которым следуют точка и идентификатор метода.  Как и любому другому идентификатору,  идентификатору  уточненного  метода, если требуется, могут предшествовать идентификатор пакета  и точка.

   уточненный идентификатор метода

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

   АД>іидентификатор объектного типаГ>і . Г>іидентификатор методаГ>

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

По умолчанию,  методы являются статическими,  однако они могут, за исключением конструкторов, быть виртуальными (посредством  включения директивы virtual в описание метода). Компилятор разрешает ссылки на вызовы статических методов во время процесса  компиляции, тогда как вызовы виртуальных методов разрешаются во время выполнения. Это иногда называют поздним связыванием.

Если объектный тип объявляет или наследует какой-либо виртуальный метод,  то переменные этого типа должны быть инициализированы посредством вызова конструктора перед вызовом любого виртуального метода.  Таким образом,  объектный тип, который описывает  или наследует виртуальный метод,  должен также описывать или наследовать по крайней мере один метод-конструктор.

Объектный тип может переопределять любой из методов, которые  он наследует от своих родителей. Если описание метода в потомке  указывает тот же идентификатор метода,  что и описание метода  в  родителе, то описание в потомке переопределяет описание в родителе. Область действия переопределяющего метода расширяется до сферы действия потомка, в котором этот метод был введен, и будет оставаться таковой,  пока идентификатор метода не будет переопределен снова.

Переопределение статического  метода не зависит от изменения  заголовка метода. В противоположность этому, переопределение вир-туального метода должно сохранять порядок,  типы и имена параметров, а также типы результатов функций, если таковые имеются. Более того,  переопределение  опять же  должно включать директиву  virtual.

Borland Pascal поддерживает дополнительные методы с  поздним связыванием, которые называются динамическими методами. Динамические методы отличаются от виртуальных только характером их диспетчеризации на этапе выполнения. Во всех других отношениях динамические методы считаются эквивалентными виртуальным.

Описание динамического метода эквивалентно  описанию  виртуального метода,  но описание динамического метода должно включать  в себя индекс динамического метода,  который  указывается непосредственно за ключевым словом virtual. Индекс динамического метода должен  быть  целочисленной  константой  в  диапазоне от 1 до  656535 и должен быть уникальным среди индексов других  динамических методов,  содержащихся в объектном типе или его предках. Например:

procedure FileOpen(var Msg: TMessage); virtual 100;

Переопределение динамического  метода должно соответствовать  порядку, типа и именам параметров и  точно  соответствовать  типу  результата функции  порождающего  метода.  Переопределение  также  должно включать в себя директиву virtual,  за которой следует тот  же индекс динамического метода, который был задан в объектном типе предка.

Примечание: Подробнее о динамических методах и о  разнице  в  диспетчеризации динамических и виртуальных методов  рассказывается в Главе 22.

Экземпляр объекта  создается посредством описание переменной  или константы  объектного типа  или путем применения стандартной  процедуры New к переменной типа указатель на объектный  тип.  Результирующий объект называется экземпляром объектного типа.

var

F: TField;

Z: TZipField;

FP: PField;

ZP: PZipField;

С учетом этих описание  переменных F  является  экземпляром  TField, а Z - экземпляром TZipField. Аналогично, после применения  New к FP и ZP,  FP будет указывать на экземпляр TField, а ZP - на  экземпляр TZipField.

Если объектный тип содержит виртуальные методы, то экземпляры этого  объектного  типа должны инициализироваться посредством  вызова конструктора перед вызовом любого виртуального метода. Ни-  же приведен пример:

var

   S: StrField;

begin

   S.Init (1, 1, 25, 'Первое имя');

   S.Put ('Френк');

   S.Display;

   ...

   S.Done;

end;

Если S.Init не вызывался, то вызов S.Display приведет к неудачному завершению данного примера.

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

Объект инициализируется  кодом, генерируемым  компилятором,  который выполняется между вызовом конструктора,  и когда выполнение фактически достигает первого оператора в блоке кода конструктора.

Если экземпляр объекта не инициализируется,  и проверка диапазона включена (директивой {$R+}),  то первый вызов виртуального  метода экземпляра объекта дает ошибку этапа выполнения. Если проверка диапазона выключена (директивой {$R-}), то первый виртуального метода неинициализированного объекта может привести  к  непредсказуемому поведению.

Правило обязательной инициализации применимо также к экземплярам, которые являются компонентами структурных типов. Например:

var

Comment: array [1..5] of TStrField;

I: integer;

begin

for I := 1 to 5 do

Comment [I].Init (1, I + 10, 40, 'первое_имя');

.

.

.

for I := 1 to 5 do Comment [I].Done;

end;

Для динамических  экземпляров инициализация,  как  правило,  связана с размещением,  а очистка - с удалением,  что достигается  благодаря расширенному  синтаксису стандартных  процедур  New и  Dispose. Например:

var

   SP: StrFieldPtr;

begin

   New (SP, Init (1, 1, 25, 'первое_имя');

   SP^.Put ('Френк');

   SP^.Display;

.

.

.

   Dispose (SP, Done);

end;

Указатель на объектный тип является совместимым по  присваиванию с указателем на любой родительский объектный  тип,  поэтому  во время  выполнения  программы указатель на объектный тип может  указывать на экземпляр этого типа или на экземпляр любого  дочернего типа.

Например, указатель  типа ZipFieldPtr  может  присваиваться  указателям типа PZipField,  PNumField и PField, а во время выполнения программы указатель типа PField может либо  иметь  значение  nil, либо указывать на экземпляр TField, TNumField или TZipField,  или на любой экземпляр дочернего по отношению к TField типа.

Эти правила совместимости указателей по присваиванию  применимы также к параметрам-переменным объектного типа. Например, методу TField.Copy  могут быть  переданы  экземпляры типов TField,  TStrField,  TNumField,  TZipField или любые другие экземпляры дочернего от TField типа.

Метод активизируется посредством оператора вызова  процедуры  или функции, состоящего из десигнатора метода, за которым следует  список параметров. Такой тип вызова называется активизацией метода.

   десигнатор метода

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

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

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

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

  А>і ссылка на переменную Г>і . ГДДДДЩ

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

Ссылка на переменную задается, если десигнатор метода должен описывать экземпляр объектного типа,  а идентификатор метода должен обозначать метод этого объектного типа.

Экземпляр, обозначенный десигнатором метода,  становится неявным фактическим параметром метода; он соответствует формальному  параметру-переменной с именем Self, который владеет объектным типом, соответствующим активизированному методу.

Для статических  методов описанный тип (на этапе компиляции)  определяет, какой из методов активизируется. Например, десигнаторы F.Init и FP^.Init всегда  активизируют  TField.Init,  так  как  описанным типом F и FP^ является TField.

Для виртуальных методов выбором экземпляра управляет  фактический тип (этапа выполнения).  Например,  десигнатор FP^.Display  может активизировать  методы TField.Display, TStrField.Display,  TNumField.Display или TZipField.Display (в зависимости от фактического типа экземпляра, указываемого FP).

В операторе with,  ссылающемся на экземпляр объектного типа,  ссылка на  переменную  в  десигнаторе метода может опускаться.  В  этом случае экземпляром, на который ссылается оператор with, становится неявный  параметр Self  активизации метода.  Аналогично,  ссылка не переменную может опускаться в  методе.  В  этом  случае  параметром Self метода, содержащего вызов, становится неявный параметр Self активизации метода.

В методе, операторе вызова функции или процедуры для обозначения активизации конкретного метода  допускается  использование  десигнатора уточненного метода. Такой тип вызова называется активизацией уточненного метода.

   десигнатор уточненного метода

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

   АДВ>і идентификатор  Г>і . ГДДДДДДД>іидентификатор методаГ>

  і і   объектного типа і АДДДЩ ^   АДДДДДДДДДДДДДДДДДДДДЩ

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

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

  А>і   inheritedГДДДДДДДДДДЩ

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

Объектный тип,  заданный в  десигнаторе уточненного метода,  должен быть таким же,  как и включающий метод объектный тип,  или  соответствовать родительскому типу.

Для обозначения родительского объектного типа или объектного  типа, включающего   метод,  можно  использовать  ключевое слово  inherited;  в методах объектного типа, не имеющего предка, ключевое слово inherited использоваться не может.

Неявный параметр Self активизации уточненного метода  становится параметром  Self метода,  содержащего  вызов. Активизация  уточненных методов  не предусматривает механизма диспетчеризации  виртуальных методов - вызов будет всегда статическим и всегда вызывает заданный метод.

Активизация уточненного метода используется обычно в переопределяющем методе для  активизации  переопределяющего метода.  С  учетом описанных выше типов приведем некоторые примеры  активизации уточненных методов:

constructor TNumField.Init(Fx, FY, Flen: Integer;

   FName: String; FMin, FMax: Longint);

begin

   inherited Init(FX, FY, FLen, FName);

   Value := 0;

   Min := FMin;

   Max := FMax;

end;

 

function TZipField.PutStr(S: String): Boolean;

begin

   PutStr := (Length(S) = 5) and TNumField.PutStr(S);

end;

Как показывают  эти примеры,  активизация уточненных методов  позволяет переопределяющему методу "вновь использовать" код метода, который он переопределяет.

Диапазон значений  множественного  типа  представляет  собой  мощность  множества  для определенного порядкового типа (базового  типа).  Каждое возможное значение множественного  типа  является  подмножеством возможных значений базового типа.

Переменная множественного типа может принимать как все значения множества, так и ни одного.

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

   тип множество ДДД>і set ГДДД>і of ГДДД>і порядковый тип ГДДД>

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

Базовый тип не должен иметь более 256 возможных  значений, и  порядковые значения верхней и нижней границы базового типа должны  не превышать диапазона от 0 до 255. В силу этого базовый тип множества не может быть коротким целым (Shortint),  целым (Integer),  длинным целым (Longint) или словом (Word).

Примечание: Операции над множественными типами описываются в разделе "Операции над множествами" в Главе 6.  В разделе "Описатели множеств" показано,  как определять значения множества.

Любой множественный тип может принимать значение [], которое

  называется пустым множеством.

Файловый тип  состоит из линейной последовательности компонентов,  которые могут иметь любой тип за исключением  файлового  типа или структурного типа,  содержащего компонент с файловым типом. Число компонентов описанием файлового типа не устанавливается.

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

  файловый тип ДДД>і file ГДДВД>і of ГДДД>і тип ГДДДДД>

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

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

Если слово  of  и тип компонента опущены,  то тип обозначает  нетипизированный файл.  Нетипизированные файлы представляют собой  каналы  ввода-вывода нижнего уровня, в основном используемые для  прямого доступа к любому файлу на диске,  независимо от его внутреннего формата.

Стандартный файловый  тип Text определяет файл,  содержащий  символы,  упорядоченные в строки. Текстовые файлы используют специальные процедуры  ввода-вывода,  которые описываются в Главе 14  "Ввод и вывод".

Cсылочный тип (указатель) определяет множество значений, которые указывают на динамические  переменные определенного  типа, называемого  базовым  типом.  Переменная ссылочного типа содержит  адрес динамической переменной в памяти.

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

   ссылочный тип ДДДДДД>і ^ ГДДД>і базовый тип ГДД>

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

 

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

   базовый тип ДДДД>і  идентификатор типа ГДДД>

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

Если базовый тип является еще не  описанным идентификатором,  то он должен быть описан в той же самой части описания типов, что  и тип указатель.

Переменной-указателю можно присвоить значение с помощью процедуры New, операции @ или функции Ptr. Процедура New отводит новую область памяти в динамически распределяемой области для динамических  переменных  и сохраняет адрес этой области в переменной  указателя. Операция @ ориентирует переменную-указатель на область  памяти, содержащую существующую переменную, включая и те переменные,  которые имеют идентификаторы. Функция Ptr ориентирует переменную-указатель на определенный адрес в памяти.

Зарезервированное слово nil обозначает константу со значением указателя, которая ни на что не указывает.

Встроенный тип  Pointer обозначает  нетипизированный указатель, то есть указатель, который не указывает ни на какой определенный тип. Переменные типа Pointer могут быть разыменованы: указание символа ^ после такой переменной вызывает появление ошибки.  Как и значение,  обозначаемое словом nil,  значения типа Pointer  совместимы со всеми другими типами указателей.

Примечание: В  разделе "Указатели и динамические переменные" в Главе 5 вы можете найти синтаксис ссылки на динамические переменные, которые указываются с помощью указателя-переменной.

Для представления указателя на строку с завершающим нулем  в  Borland Pascal имеется предопределенный тип PChar. В блоке System  данный тип описывается следующим образом:

type PChar = ^Char;

Borland Pascal поддерживает набор расширенных правил, позволяющих работать  со строками с завершающим нулем, используя тип  PChar. Полностью эта тема обсуждается в Главе  18  "Использование  строк с завершающим нулем".

В стандартном  Паскале процедуры  и функции рассматриваются  только как части программы, которые можно выполнять с помощью вызова процедуры или функции. В Borland Pascal процедуры и функции  трактуются гораздо шире: здесь допускается интерпретация процедур  и функций,  как объектов,  которые можно присваивать переменным и  передавать в качестве параметров.  Такие действия можно выполнять  с помощью процедурных типов.

В описании процедурного типа задаются параметры, а для функции - результат функции.

  процедурный тип

   і

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

   АВ>іprocedureГДВДДДДДДДДДДДДДДДДДД>

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

і АД>ісписок формальных параметровГДЩ  і

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

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

  А>іfunctionГВДДД>і : Г>ірезультатГЩ

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

   А>ісписок формальных параметровГЩ

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

Характерно, что синтаксис записи процедурного типа в точности совпадает с записью заголовка процедуры  или  функции,  только  опускается  идентификатор  после  ключевого слова  procedure или  function.  Приведем некоторые примеры описаний процедурного типа:

type

Proc = procedure;

SwapProc = procedure(var X, Y: Integer);

    StrProc = procedure(S: String);

MathFunc = function(X: Real): Real;

DeviceFunc = function(var F: text): Integer;

MaxFunc = function(A, B: Real; F: MathFunc): Real;

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

Borland Pascal не позволяет описывать функции, которые возвращают значения процедурного типа.  Результат функции должен быть  строкового, вещественного, целого, символьного, булевского типа,  указателем  или иметь перечислимый тип, определенный пользователем.

Переменной процедурного  типа можно  присвоить  процедурное  значение. Процедурные значения могут быть следующими:

* значениями nil;

* ссылкой на переменную процедурного типа;

* идентификатором процедуры или функции.

В контексте  процедурных значений  описание  процедуры или  функции можно  рассматривать  как  специальный вид описаний констант, когда значением константы является процедура  или  функция.

Рассмотрим, например, следующее описание:

var

P: SwapProc;

F: MathFunc;

 

procedure Swap(var A, B: Integer); far;

    var

   Temp: Integer;

begin

   Temp := A;

   A := B;

   B := Temp;

end;

 

function Tan(Angle: Real); far;

begin

   Tan := Sin(Angle) / Cos(Angle);

end;

Переменным P и F можно присвоить значения следующим образом:

P := Swap;

F := Tan;

  а вызовы с помощью P и F можно выполнить так:

P(I, J);   { эквивалентно Swap(I, J) }

X := F(X); { эквивалентно X := Tan(X) }

Использование процедурных  переменных, которым  в операторе  вызова процедуры или функции присваивается значение nil, приводит  к ошибке.  Значение nil предназначено для указания того, что процедурная переменная не присвоена, и, так где процедурная переменная может  получить значение nil, участвующие в этой процедурной  переменной вызовы процедур и функций следует подвергать проверке:

if @P <> nil then P(I, J);

Обратите внимание на использование операции @  для  указания  того, что P проверяется, а не вызывается.

Чтобы они считались совместимыми,  процедурные  типы должны  иметь одно и то же число параметров,  а параметры в соответствующих позициях должны иметь тождественные  типы.  При определении  совместимости процедурных типов имена параметров значения не имеют. Значение nil совместимо с любым процедурным типом.

Чтобы использоваться в качестве процедурных значений, процедуры и  функции  должны описываться с директивой far и компилироваться в состоянии с {$F+}.  Кроме того, в качестве  процедурных  значений не  могут  указываться  стандартные процедуры и функции,  вложенные процедуры и функции,  методы, процедуры и функции, описанные с ключевым словом inline или interrupt.

Стандартные процедуры и функции - это подпрограммы,  описанные в модуле Unit,  например, WriteLn, ReadLn, Chr или Ord. Чтобы  использовать в  качестве процедурного значения стандартную процедуру и функцию,  напишите для нее "оболочку". Например, следующая  функция DSin  совместима  по  присваиванию с описанным выше типом  MathFunc:

    function FSin(X: Real): Real; far;

begin

   FSin := Sin(X);

end;

Процедура или функция является вложенной, когда она описывается внутри другой процедуры или функции.  Такие вложенные процедуры и  функции  не  могут использоваться в качестве процедурных  значений.

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

Тождественность типов требуется только для переменных фактических и формальных параметров при вызове процедур и функций.

Два типа,  скажем T1 и T2, являются тождественными, если является истинным одно из следующих утверждений:  T1 и T2 представляю собой один и тот же идентификатор типа; T1 описан как эквивалентный типу, тождественному T2.

Второе условие означает,  что T1 не обязательно должен  быть  описан  как непосредственно эквивалентный T2.  Следующие описания  типов:

T1 = integer;

T2 = T1;

T3 = integer;

T4 = T2;

означают, что T1,  T2, T3,  T4 и integer являются тождественными  типами. Следующие описания типов:

T5 = set of integer;

T6 = set of integer;

не определяют T5 и T6 как тождественные, поскольку set of integer не является идентификатором типа. Две переменные, описанные в одном и том же описании, например:

V1, V2: set of integer;

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

Описания:

V1: set of integer;

V2: set of integer;

V3: integer;

V4: integer;

означают, что V3 и V4 имеют тождественный тип, а V1 и V2 - нет.

Иногда, например, в выражениях и операциях сравнения, требуется совместимость типов.  Совместимость типов, кроме того, является важной предпосылкой для совместимости по присваиванию.

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

* Оба типа являются одинаковыми.

* Оба типа являются вещественными типами.

* Оба типа являются целочисленными.

* Один тип является поддиапазоном другого.

* Оба типа являются отрезками одного и того же основного типа.

* Оба типа являются множественными типами с совместимыми базовыми типами.

* Один тип является строковым типом,  а другой  - строковым  типом, упакованным строковым типом или типом PChar;

* Один  тип  -  это тип Pointer,  а другой - любой ссылочный   тип.

* Один тип является типом PChar,  а другой - символьным массивом  с нулевой базой вида array[0..X] of Char (это действует только при разрешении директивой {$X+}  расширенного  синтаксиса).

* Оба  типа являются указателями идентичных типов (это действует только при разрешении указателя с проверкой типа директивой {$X+}).

* Оба  типа  являются процедурными с идентичными типами результатов,  одинаковым числом параметров  и соответствием между параметрами.

Совместимость по присваиванию необходима,  если имеет  место присваивание значения, например, в операторе присваивания или при  передаче значений параметров.

Значение типа T1 является совместимым по присваиванию с  типом T2 (то есть допустим оператор T1:=T2),  если выполняется одно  из следующих условий:

* T1 и T2 имеют тождественные типы,  и ни один из них не является  файловым типом или структурным типом, содержащим  компонент с файловым типом на одном из своих уровней.

* T1 и T2 являются совместимыми порядковыми типами, и значения типа T2 попадают в диапазон возможных значений T1.

* T1 и T2 являются вещественными типами,  и значения типа T2  попадают в диапазон возможных значений T1.

* T1 является вещественным типом,  а T2 является целочисленным типом.

* T1 и T2 являются строковыми типами.

* T1 является строковым типом,  а T2 является символьным типом (Char).

* T1 является строковым типом,  а  T2  является  упакованным  строковым типом.

* T1  и T2 являются совместимыми упакованными строковыми типами.

* T1 и T2 являются совместимыми множественными типами, и все  члены  значения типа T2 попадают в диапазон возможных значений T1.

* T1 и T2 являются совместимыми типами указателей.

* T1 - это тип PChar,  а T2 - это строковая  константа (это  действует только при разрешении директивой {$X+} расширенного синтаксиса).

* T1 является типом PChar,  а T2 - символьным массивом с нулевой базой вида array[0..X] of Char (это действует только  при разрешении директивой {$X+} расширенного синтаксиса).

* T1 и T2 являются совместимыми процедурными типами.

* T1 представляет собой процедурный тип,  а T2  - процедура  или функция с идентичным типом результата, идентичным числом параметров и соответствием между типами параметров.

* Объектный тип T2 совместим по присваиванию с объектным типом T1, если T2 является доменом T1.

* Тип указателя Р2, указывающий на объект типа Т3, совместим по присваиванию с типом указателя P1,  указывающим на объект T1, если T2 является доменом T1.

На этапе компиляции и выполнения выдается сообщение об ошибке, если совместимость по присваиванию необходима,  а ни одно из условий предыдущего списка не выполнено.

Программы, процедуры и функции имеют для описания типов специальный раздел описания типов. Например:

type

   TRange  = integer;

   TNumber = integer;

   TColor  = (red,green,blue);

   TTextIndex = 1..100;

  TTestValue = -99..99;

   TTestList  = array[TestIndex] of TestValue;

   PestList   = ^TTestList;

   TDate   = object

year: integer;

month: 1..12;

day: 1.. 31;

  procedure SetDate(D, M, Y: Integer);

  function ShowDate: String;

  end;

 

    MeasureData = record

  when: Date;

  count: TTestIndex;

  data: TestListPtr;

   end;

TMeasureList = array[1..50] of MeasureData;

TName  = string[80];

TSex   = (male,female);

TPersonDate  = ^TPersonData;

TPersonData  = record

  name,firstName: TName;

  age:   integer;

  married:  boolean;

 father,child,sibling: Person;

case s: Sex of

   male:   (bearded: boolean);

  female: (pregnant: boolean);

end;

TPersonDate = array[0..SizeOf(TPersonDate)-1] of Byte;

TPeople  = file of TPersonData;

 

В этом примере Range,  Number и Integer являются тождественными типами. TTestIndex является просто совместимым и совместимым  по присваиванию,  но не тождественным,  с типами Number,  Range и  Integer. Обратите  внимание на использование в описаниях TCharVal  и TPersonBuf выражений-констант.