
Глава 3. Типы
При описании переменной необходимо указать ее тип. Тип переменной описывает набор значений, которые она может принимать, и действия, которые могут быть над ней выполнены. Описание типа определяет идентификатор, который обозначает этот тип.
┌─────────────┐ ╒═╕ ┌───┐ ╒═╕
описание типа───│идентификатор├───│=├───│тип├───│;├──
└─────────────┘ ╘═╛ └───┘ ╘═╛
┌───────────┐
тип ─────────│простой тип├────────────────────
│ └───────────┘ ‑
│ ┌───────────────┐ │
├────│тип "указатель"├──────┤
│ └───────────────┘ │
│ ┌───────────────┐ │
├────│структурный тип├──────┤
│ └───────────────┘ │
│ ┌─────────────┐ │
├────│строковый тип├────────┤
│ └─────────────┘ │
│ ┌──────────────────┐ │
└────│идентификатор типа├───┘
└──────────────────┘
Указание идентификатора в левой части описания типа означает, что он определен как идентификатор типа для блока, в котором указано это описание типа. Область действия идентификатора типа не включает его самого, исключение составляют типы указатель.
Имеется шесть следующих основных классов типов:
- простой тип;
- строковый тип;
- структурный тип;
- тип указатель;
- процедурный тип;
- объектный тип.
Простые типы
Простые типы определяют упорядоченные множества значений.
┌──────────────┐
простой тип ────┬─│порядковый тип├────────────
│ └──────────────┘ ‑
│ │
│ ┌────────────────┐ │
└─│вещественный тип├────┘
└────────────────┘
┌────────────────────────────────┐
вещественный тип ────│идентификатор вещественного типа├───
└────────────────────────────────┘
Идентификатор вещественного типа относится к числу стандартных идентификаторов, которые могут быть вещественными (Real), с одинарной точностью (Single), с двойной точностью (Double), с повышенной точностью (Extended) и сложными (Comp).
Примечание: В Главe 1 вы можете найти описание того, как обозначать константы целого и вещественного типов.
Порядковые типы
Порядковые типы представляют собой подмножество простых типов. Все простые типы, отличные от вещественных типов, являются порядковыми и выделяются по следующим четырем характеристикам.
- Все возможные значения данного порядкового типа представляют собой упорядоченное множество, и каждое возможное значение связано с порядковым номером, который представляет собой целочисленное значение. За исключением значений целочисленного типа, первое значение любого порядкового типа имеет порядковый номер 0, следующее значение имеет порядковый номер 1 и так далее для каждого значения в этом порядковом типе. Порядковым номером значения целочисленного типа является само это значение. В любом порядковом типе каждому значению, кроме первого, предшествует другое значение, и после каждого значения, кроме последнего, следует другое значение в соответствии с упорядоченностью типа.
- К любому значению порядкового типа можно применить стандартную функцию Ord, возвращающую порядковый номер этого значения.
- К любому значению порядкового типа можно применить стандартную функцию Pred, возвращающую предшествющее этому значению значение. Если эта функция применяется к первому значению в этом порядковом типе, то выдается сообщение об ошибке.
- К любому значению порядкового типа можно применить стандартную функцию Succ, возвращающую следующее за этим значением значение. Если эта функция применяется к последнему значению в этом порядковом типе, то выдается сообщение об ошибке.
Синтаксис порядкового типа имеет следующий вид:
┌────────────────┐
порядковый тип ─┬──│ отрезок типа ├───────────────────
│ └────────────────┘ ‑
│ ┌────────────────┐ │
├──│перечислимый тип├────────────────┤
│ └────────────────┘ │
│ ┌──────────────────────────────┐ │
└──│идентификатор порядкового типа├──┘
└──────────────────────────────┘
Турбо Паскаль имеет девять встроенных порядковых типов: integer (целое), shortint (короткое целое), longint (длинное целое), byte (длиной в байт), word (длиной в слово), boolean (булевское), wordbool (булевское размером в слово), longbool (длинное булевское) и char (символьный). Кроме того, имеется два других класса определяемых пользователем порядковых типов: перечислимые типы и отрезки типов (поддиапазоны).
Целочисленный тип
В Турбо Паскале имеется пять предопределенных целочисленных типов: shortint (короткое целое), integer (целое), longint (длинное целое), byte (длиной в байт) и word (длиной в слово). Каждый тип обозначает определенное подмножество целых чисел, как это показано в следующей таблице.
Таблица 3.1 Предопределенные целочисленные типы
────────────────────────────────────────────────────────────
Тип Диапазон Формат
────────────────────────────────────────────────────────────
короткое целое -128 .. 127 8 бит со знаком
(Shortint)
целое -32768 .. 32767 16 бит со знаком
(Integer)
длинное целое -2147483648 .. 2147483647 32 бита со знаком
(Longint)
длиной в байт 0 .. 255 8 бит без знака
(Byte)
длиной в слово 0 .. 65535 16 бит без знака
(Word)
────────────────────────────────────────────────────────────
Арифметические действия над операндами целочисленного типа предполагают 8-битовую, 16-битовую и 32-битовую точность в соответствии со следующими правилами:
- Тип целой константы представляет собой встроенный целочисленный тип с наименьшим диапазоном, включающим значение этой целой константы.
- В случае бинарной операции (операции, использующей два операнда), оба операнда преобразуются к их общему типу перед тем, как над ними совершается действие. Общим типом является встроенный целочисленный тип с наименьшим диапазоном, включающим все возможные значения обоих типов. Например, общим типом для целого и целого длиной в байт является целое, а общим типом для целого и целого длиной в слово является длинное целое. Действие выполняется в соответствии с точностью общего типа и типом результата является общий тип.
- Выражение справа в операторе присваивания вычисляется независимо от размера или типа переменной слева.
- Любые операнды размером в байт преобразуются к промежуточному операнду размером в слово, который совместим перед выполнением арифметической операции с типами Integer и Word.
Значение одного целочисленного типа может быть явным образом преобразовано к другому целочисленному типу с помощью приведения типов.
Примечание: Приведение типов описывается в Главах 4 и 6.
Булевский тип
Значения булевского типа обозначаются встроенными идентификаторами констант False и True. Поскольку булевский тип (Boolean) является перечислимым, между этими значениями имеют место следующие отношения:
- False < True
- Ord(False) = 0
- Ord(True) = 1
- Succ(False) = True
- Pred(True) = False
Символьный тип (char)
Множеством значений этого типа являются символы, упорядоченные в соответствии с расширенным набором символов кода 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
Переменная отрезка типа имеет все свойства переменных главного типа, однако ее значение на этапе выполнения должно принадлежать указанному интервалу.
Вещественный тип
К вещественному типу относится подмножество вещественных чисел, которые могут быть представлены в формате с плавающей точкой с фиксированным числом цифр. Запись значения в формате с плавающей точкой обычно включает три значения - m, b и e - таким образом, что m x b^e=n, где b всегда равно 2, а m и e являются целочисленными значениями в диапазоне вещественного типа. Эти значения m и e далее определяют диапазон представления и точность вещественного типа.
Имеется пять видов вещественных типов: вещественное (Real), с одинарной точностью (Single), с двойной точностью (Double), с повышенной точностью (Extended) и сложное (Comp). Действия над типами с одинарной точностью, с двойной точностью и с повышенной точностью и над сложным типом могут выполняться только при наличии числового сопроцессора 8087 (который был описан ранее).
Вещественные типы различаются диапазоном и точностью связанных с ними значений (см. Таблицу 3.2).
Таблица 3.2 Диапазон представления
и десятичные цифры для вещественных типов
─────────────────────────────────────────────────────────────────────────────
Тип Диапазон Значащие цифры Размер
в байтах
─────────────────────────────────────────────────────────────────────────────
вещественное от 2.9x10^-39 до 1.7x10^38 от 11 до 12 6
(real)
с одинарной точностью от 1.5x10^-45 до 3.4x10^38 от 7 до 8 4
(single)
с двойной точностью от 5.0x10^-324 до 1.7x10^308 от 15 до 16 8
(double)
с повышенной точностью от 1.9x10^-4951 до 1.1x10^4932 от 19 до 20 10
(extended)
сложный от -2^63+1 до 2^63-1 от 19 до 20 8
(comp)
─────────────────────────────────────────────────────────────────────────────
Примечание: Сложный тип содержит только целочисленные значения в диапазоне от -2^63+1 до 2^63-1, что приблизительно равно -9.2x10^18 и 9.2x10^18.
Турбо Паскаль поддерживает две модели генерации кода для выполнения действий над вещественными типами: программную для чисел с плавающей точкой и аппаратную для чисел с плавающей точкой. Выбор соответствующей модели осуществляется с помощью директивы компилятора $N.
Программная поддержка чисел с плавающей точкой
В состоянии {$N-}, которое устанавливается по умолчанию, генерируемый код выполняет все вычисления с вещественными типами программно, через вызов подпрограмм библиотеки исполняющей системы. Из-за соображений скорости и размера кода в этом состоянии допускаются только действия над переменными типа real (вещественное). Любая попытка оттранслировать операторы, выполняющие действия над типами с одинарной точностью, с двойной точностью, с повышенной точностью и над сложными типами, вызовет сообщение об ошибке.
Аппаратная поддержка чисел с плавающей точкой (80x87)
В состоянии {$N+} генерируемый код выполняет все вычисления над вещественными типами с помощью числового сопроцессора 80x87. Это состояние позволяет использовать все вещественные типы, однако оно требует наличия сопроцессора 80x87 на этапе компиляции и выполнения.
Строковые типы
Значением строкового типа является последовательность символов с динамическим атрибутом длины (в зависимости от действительного числа символов при выполнении программы) и постоянным атрибутом размера в диапазоне от 1 до 255. Текущее значение атрибута длины можно получить с помощью стандартной функции Length.
╒══════╕
строковый тип ──│string├─┬──────────────────────────────────
╘══════╛ │ ‑
│ ╒═╕ ┌───────────────┐ ╒═╕ │
└─│[├─│целое без знака├──│]├──┘
╘═╛ └───────────────┘ ╘═╛
Отношение между любыми двумя строковыми значениями устанавливается согласно отношению порядка между значениями символов в соответствующих позициях. В двух строках разной длины каждый символ более длинной строки без соответствующего символа в более короткой строке принимает значение "больше"; например, 'Xs' больше, чем 'X'. Нулевые строки могут быть равны только другим нулевым строкам и являются наименьшими строковыми значениями.
К символам в строке можно обращаться, как к компонентам массива.
Примечание: См.раздел "Массивы, строки и индексы" в Главе 4.
Структурные типы
Структурный тип, характеризуемый методом структурирования и типами своих компонентов, имеет более одного значения. Если тип компонента является структурным, то получаемый в результате структурный тип имеет более одного уровня структурирования. Структурный тип может иметь неограниченные уровни структурирования.
┌────────────┐
структурный тип─┬─────────────┬──│ тип массив ├───────────
│ ‑ │ └────────────┘ ‑
│ ╒══════╕ │ │ ┌─────────────────┐ │
└─│packed├─┘ ├──│множественный тип├───┤
╘══════╛ │ └─────────────────┘ │
│ ┌────────────┐ │
├──│файловый тип├────────┤
│ └────────────┘ │
│ ┌─────────────┐ │
├──│объектный тип├───────┤
│ └─────────────┘ │
│ ┌────────────┐ │
└──│ тип запись ├────────┘
└────────────┘
Слово packed (упакованный) в описании структурного типа требует от компилятора уплотнить хранимые данные, даже за счет уменьшения скорости доступа к компоненту в переменной этого типа. Слово packed не имеет никакого действия в Турбо Паскале, поскольку упаковка выполняется здесь автоматически всюду, где это возможно.
Типы массив
Массивы содержат фиксированное число компонентов одного типа, так называемого типа конпонента. На приводимой ниже синтаксической диаграмме тип компонента следует за словом 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
Для доступа к элементам массива необходимо указать идентификатор массива с одним или несколькими индексами в квадратных скобках
Примечание: См. раздел "Массивы, Строки и индексы" в Главе 4.
Тип массив, имеющий вид:
packed array[m..n] of char
где m меньше, чем n, называется упакованным строковым типом (слово packed можно опустить, поскольку оно не оказывает действия в Турбо Паскале). Упакованный строковый тип имеет некоторые свойства, не характерные для других типов массив.
Примечание: См. "Тождественные и совместимые типы" далее в этой главе.
Тип массива вида:
array[0..X] of Char
где X - положительное ненулевое целое, называется массивом с нулевой базой. Символьный массив с нулевой базой используется для хранения строк, завершающихся нулем. При разрешении расширенного синтаксиса (директива компилятора {$X+}) символьный массив с нулевой базой совместим со значением PChar. Полное обсуждение данного вопроса вы можете найти в Главе 13 "Модуль String".
Типы запись
Тип запись содержит установленное число элементов или полей, которые могут быть различных типов. Описание типа запись указывает тип каждого поля и идентификатор, который именует поле.
╒══════╕ ╒══════╕
тип запись ────│record├─┬─────────────────────│ end ├────
╘══════╛ │ ‑ ╘══════╛
│ ┌────────────┐ │
└─│список полей├──┘
└────────────┘
┌─────────────┐
список─┬─│фиксированная├─┬─────────────────────────┬─────────
полей │ │часть │ │ ‑ │ ‑
│ └─────────────┘ │ ╒═╕ ┌──────────┐ │ │ ╒═╕ │
│ └─│;├───│вариантная├─┘ └─│;├─┘
│ ╘═╛ ‑ │часть │ ╘═╛
│ │ └──────────┘
└─────────────────────────┘
┌──────────────────────┐ ╒═╕ ┌───┐
фиксированная────│список идентификаторов├──│:├──│тип├──┬───
часть ‑ └──────────────────────┘ ╘═╛ └───┘ │
│ ╒═╕ │
└───────────────┤;│────────────────────────┘
╘═╛
Фиксированная часть типа запись содержит список фиксированных полей вместе с идентификатором и типом для каждого поля. Каждое поле содержит информацию, которая всегда отыскивается одним и тем же способом.
Приведем пример типа запись:
record
year: integer;
month: 1..12;
day: 1..31;
end
В вариантной части, изображенной на синтаксической диаграмме описания типа запись, память распределяется более чем для одного списка полей, поэтому доступ к информации может быть осуществлен более чем одним способом. Каждый список полей является вариантом. Варианты налагаются друг на друга в памяти, поэтому в любое время возможен доступ ко всем полям во всех вариантах.
вариант-
ная ╒════╕ ┌────────┐ ╒══╕ ┌───────┐
часть-│case├┬───────────────────│тип поля│-│of├──│вариант├─┬
╘════╛│ ‑ │признака│ ╘══╛‑ └───────┘ │
│ ┌────────┐ ╒═╕ │ └────────┘ │ ╒═╕ │
└─│иденти- ├─│:├─┘ └────│;├────┘
│фикатор │ ╘═╛ ╘═╛
└────────┘
┌──────────────────────────────┐ тип поля признака────│идентификатор порядкового типа├──────────
└──────────────────────────────┘
┌─────────┐ ╒═╕ ╒═╕ ╒═╕ вариант────│константа├─┬─│:├──│(├─┬───────────────────│)├───
‑ └─────────┘ │ ╘═╛ ╘═╛ │ ‑ ╘═╛
│ ╒═╕ │ │ ┌────────────┐ │
└──────│,├──────┘ └─│список полей├─┘
╘═╛ └────────────┘
Вы можете видеть на схеме, что каждый вариант идентифицирован по крайней мере одной константой. Все константы должны быть отличными друг от друга и иметь порядковый тип, совместимый с типом поля признака. Доступ к вариантным и фиксированным полям один и тот же.
В вариантной части можно указать необязательный идентификатор - идентификатор признака (тега) поля. При наличии идентификатора признака поля он становится идентификатором дополнительного фиксированного поля записи - поля признака. Программа может использовать значение поля признака для указания, какой вариант является активным в настоящий момент. Без указания поля признака программа выбирает вариант по другому критерию.
Ниже приводятся несколько примеров типов запись:
type
Person = 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;
Polygon = record
x,y : real;
case kind : Figure of
rectangle : (height,wigth: real);
triangle : (side1,side2,angle: real);
circle : (radius: real);
end
Объектные типы
Объектный тип является структурой, состоящей из фиксированного числа компонентов. Каждый компонент является либо полем, содержащим данные строго определенного типа, либо методом, выполняющим операции над объектом. По аналогии с описанием переменных, описание поля указывает тип данных этого поля и идентификатор, именующий поле: по аналогии с описанием процедуры или функции, описание метода указывает заголовок процедуры, функции, конструктора или деструктора.
Объектный тип может наследовать компоненты другого объектного типа. Если T2 наследует от T1, то T2 является потомком T1, а T1 является родителем T2.
Наследование является транзитивным, то есть если T3 наследует от T2, а T2 наследует от T1, то T3 наследует от T1. Область (домен) объектного типа состоит из него самого и из всех его наследников.
╒══════╕
Объектный тип ─│object├────┬────────────────┬──────────────┬─┐
╘══════╛ │ ‑ │ │ │
│ │ │ │ │
│ ┌─────────── │ │ ┌──────────┐ │ │
└│ наследо- ├─┘ └│ список ├─┘ │
│ вание │ │ полей │ │
└──────────┘ └──────────┘ │
┌────────────────────────────────────────────────────┘
│ ╒══════╕
└─┬───────────────────────────────────────┤ end ├────
│ ‑ ╘══════╛
│ ╒═╕ ┌─────────────────┐ │
└──│;├──────│ список методов ├──┘
╘═╛ └─────────────────┘
╒═╕ ┌────────────────────────────┐ ╒═╕
Наследование ──│(├───│ идентификатор типа объекта ├──│)├─────
╘═╛ └────────────────────────────┘ ╘═╛
┌───────────────────────┐ ╒═╕ ┌─────┐ ╒═╕
Список полей ─────│ список идентификатора ├───│:├────┤ тип ├│;├┬─
‑ └───────────────────────┘ ╘═╛ └─────┘ ╘═╛│
│ │
└──────────────────────────────────────────────────┘
┌──────────────────┐ ╒═╕
Список методов ──│ заголовок метода ├─┬──────────────────────────┬┤;├─┬─
‑ └──────────────────┘ │ │╘═╛ │
│ │ ╒═╕ ╒═════════╕ │ │
│ └│;├────│ virtual ├┬────┬┘ │
│ ╘═╛ ╘═════════╛│ │ │