С помощью именования константных значений программист может изменять эти значения для всей программы без необходимости искать их править в коде.
Константные значения могут быть заданы именами с использованием объявлений, как следующие:
CONST
LastCh = ‘#’;
FieldWidth = 4;
Max = 9999;
Min = -Max;
Name = ‘Blaise Pascal’;
Поскольку константный идентификатор, представленный объявлением константы, именует значение, он имеет тот же тип и может появляться везде, где могут встречаться значения этого типа. В следующем примере, использующем приведенное выше объявление констант, Min и Max используются для объявления диапазона, LastCh сравнивается с символьным значением, FieldWidth управляет размером поля в котором распечатываются значения типа SmallInt, Name используется в операторе Write.
TYPE
SmallInt = Min .. Max;
VAR
Value: SmallInt;
Ch: CHAR;
BEGIN
...
WHILE Ch <> LastCh
DO
...
READ(Value);
WRITELN(Value:FieldWidth);
WRITELN(Name);
...
END
Синтаксис для раздела объявлений констант представлен ниже.
Контекстное правило, которое сопровождает данные синтаксические правила утверждает, что только <идентификаторы> которые появляются в <объявлении констант> являются <константными идентификаторами>. Эти специальные идентификаторы не могут быть использованы как если бы они были переменными, потому что их значения фиксированы. Например, константный идентификатор не может появляться в левой части оператора присваивания или как фактический параметр, соответствующий формальному VAR параметру.
Константные идентификаторы помогаю документировать программы и облегчают последующие изменения программ. Объявление константы LastCh с фиксированным значением # и использование LastCh вместо литерала ‘#’ улучшает программу. Рассмотрим следующий фрагмент:
CONST
LastCh = ‘#’;
VAR
Ch: CHAR;
BEGIN
WHILE Ch <> LastCh
DO
...
WRITELN(‘Инвентарный #:’)
END
Если мы решили заканчивать входную последовательность другим символом, (например $), нам необходимо всего лишь изменить только объявление соответствующей константы:
CONST
LastCh = ‘$’;
Поиск и замена # на $ по всему телу программы одновременно и утомительно и чревато внесением ошибок. Например, мы по ошибке можем заменить # на $ в последнем операторе WRITE.
Типы
Поскольку типы являются важной частью Паскаля, важно иметь возможность именовать их и использовать имя вместо полного описания типа, когда это необходимо. Однажды описав сложный тип, программист может предотвратить ошибки связанные со случайными изменениями и легко изменять каждое вхождение этого типа.
Хотя типы данных описывают наборы значений и операции, которые могут быть к ним применимы, объявления типов Паскаля описывают только представление значений. Новые типы объявленные в <разделе объявлений типов> блока связыванием идентификатора (имени нового типа) с описанием его значений (например, списком констант перечислимого типа или границами диапазона). Несколько примеров новых типов представлены ниже:
TYPE
CType = CHAR;
Ct = CType;
Month = (NoMonth, Jan, Feb, Mar, Apr, May, Jun,
Jul, Aug, Sep, Oct, Nov, Dec);
Summer = Jun .. Aug;
DayNum = 1 .. 31;
Letter = ‘A’ .. ‘Z’;
Идентификаторы как Letter могут встречаться везде, где встречаются в объявлениях списках формальных параметров. Идентификаторы типов – это удобное сокращение – именуя список констант, идентификаторы как Month могут легко повторяться в программе без опасности, что объявление тип может быть задано некорректно.
Синтаксис объявления типа приведен ниже:
<раздел объявлений типов> ::= TYPE <объявления типов> |
<параметр переменная> ::= VAR <список идентификаторов> : <идентификатор типа>
Каждый формальный параметр должен быть объявлен с идентификатором типа.
Таким образом, ни один из формальных параметров не в следующем заголовке процедуры не объявлен корректно:
PROCEDURE Proc
(VAR Mo: (NoMonth, Jan, Feb, Mar, Apr, May
b Jun, Jul, Aug, Sep, Oct, Nov, Dec);
VAR Day: 1..31;
VAR Finitial, Linitial: ‘A’ .. ‘Z’);
поскольку они все объявлены не с помощью идентификаторов типа. Заголовок процедуры может быть записан корректно с помощью предшествующего введения объявлений типов.
TYPE
Month = (NoMonth, Jan, Feb, Mar, Apr, May, Jun,
Jul, Aug, Sep, Oct, Nov, Dec);
DayNum = 1 ..31;
Letter = ‘A’ .. ‘Z’;
PROCEDURE Proc (VAR Mo: Month; VAR Day: DayNum;
VAR Finitial, Linitial: Letter);
Способность объявления новых типов поднимает вопрос эквивалентности типов: когда два типа являются одним и тем же? Многие операции в программе зависят от операндов, имеющих соответствие типов и Паскаль имеет три степени совместимости типов для обработки различных ситуаций: одинаковый, совместимый для присваивания, и совместимый.
1. Фактические параметры должны иметь одинаковые типы, что и соответствующие формальные параметры.
2. Тип переменной в левой части присваивания должен быть совместим для присваивания с типом выражения в правой части.
3. Операнды операций сравнения должны иметь совместимые типы.
В Паскале два типа являются одинаковыми, если они были определены как эквивалентные в объявлениях типов. Переменные имеют одинаковый тип если они объявлены с идентификаторами типов, которые являются одинаковыми, или одинаковый тип объявлен вместе с объявлением переменной. Например, рассмотрим объявления:
TYPE
T1 = INTEGER;
T2 = T1;
SmallInt = 0 .. 9;
Age = 0 .. 9;
VAR
W: SmallInt;
X: 0 ..9;
Y, Z: 0 .. 9;
Типы INTEGER, T1 и T2 в примере выше являются одинаковыми. SmallInt и Age не являются одинаковыми. Y и Z имеют одинаковый тип, но технически X имеет различный тип.
В следующем фрагменте программы на Паскале, используя выше приведенные объявления, только W может быть передано P, поскольку это единственная переменная тот же типа что и Parm.
PROCEDURE P (VAR Parm: SmallInt);
...
P(W); {допустимо – Parm и W имеют одинаковый тип SmallInt}
P(X); {недопустимо – Parm и X имеют разные типы}
P(Y); {недопустимо – Parm и Y имеют разные типы}
...
Два типа, T1 и T2, совместимы если справедливо следующее:
· T1 и T2 имеют одинаковый тип.
· T1 является диапазоном T2 или T2 является диапазоном T1 или оба типа являются диапазонами одного владеющего типа.
В примере выше, тип X совместим с Y, потому что оба являются диапазонами INTEGER. Переменные Letter и Digit в следующем примере имеют совместимые типы, потому что оба типа определяют диапазон одного владеющего типа CHAR.
VAR
Letter: ‘A’ .. ‘Z’;
Digit: ‘0’ .. ’9’;
BEGIN
...
IF (Digit <= ‘0’) OR (Digit = Letter)
...
END
Таким образом, Digit может быть сравнена с константой ‘0’ типа CHAR и с Letter.
Значение типа T2 совместимо для присваивания с типом T1. если выполняется одно из следующих условий:
· T1 и T2 имеют одинаковый тип (но не файловый тип)
· T1 и T2 совместимые порядковые типы и значение типа T2 лежит в интервале возможных значений T1.
В следующем примере только первые два оператора присваивания допустимы.
TYPE
SmallInt = 0 .. 99;
SmallerInt = 0 .. 9;
VAR
X: SmallInt;
Y: SmallerInt;
BEGIN
X := 0; {Тип X (SmallInt) совместим с типом 0 (INTEGER)
и 0 лежит в интервале возможных значений типа
SmallInt}
Y := X; {Тип Y (SmallerInt) совместим с типом X
(SmallInt) и значение X (0) лежит в интервале
возможных значений типа SmallerInt}
Y := X - 1; {Тип Y (SmallInt) совместим с типом 0 (INTEGER)