В нескольких местах в языке "C" требуются выражения, ко- торые после вычисления
становятся константами: после вариан- тного префикса CASE, в качестве границ массивов
и в инициа- лизаторах. В первых двух случаях выражение может содержать только целые
константы, символьные константы и выражения SIZEOF, возможно связанные либо бинарными
операциями
+ - * / . % & \! Ч << >> == 1= <> <= >=
либо унарными операциями
- \^
либо тернарной операцией ?:
Круглые скобки могут использоваться для группировки, но не для обращения к функциям.
В случае инициализаторов допускается большая (ударение на букву о) свобода; кроме
перечисленных выше константных выражений можно также применять унарную операцию
& к внешним или статическим объектам и к внешним или статическим масси- вам, имеющим
в качестве индексов константное выражение. Унарная операция & может быть также применена
неявно, в ре- зультате появления неиндексированных массивов и функций. Ос- новное
правило заключается в том, что после вычисления ини- циализатор должен становится
либо константой, либо адресом ранее описанного внешнего или статического объекта
плюс или минус константа.
24. Соображения о переносимости
Некоторые части языка "C" по своей сути машинно-зависи- мы. Следующие ниже перечисление
потенциальных трудностей хо- тя и не являются всеобъемлющими, но выделяет основные
из них.
Как показала практика, вопросы, целиком связанные с ап- паратным оборудованием,
такие как размер слова, свойства плавающей арифметики и целого деления, не представляют
осо- бенных затруднений. Другие аспекты аппаратных средств нахо- дят свое отражение
в различных реализациях. Некоторые из них, в частности, знаковое расширение (преобразующее
отрица- тельный символ в отрицательное целое) и порядок, в котором помещаются байты
в слове, представляют собой неприятность, которая должна тщательно отслеживаться.
Большинство из ос- тальных проблем этого типа не вызывает сколько-нибудь значи-
тельных затруднений.
Число переменных типа REGISTER, которое фактически может быть помещено в регистры,
меняется от машины к машине, также как и набор допустимых для них типов. Тем не
менее все ком- пиляторы на своих машинах работают надлежащим образом; лиш- ние или
недопустимые регистровые описания игнорируются.
Некоторые трудности возникают только при использовании сомнительной практики
программирования. Писать программы, которые зависят от каких- либо этих свойств,
является чрез- вычайно неразумным.
Языком не указывается порядок вычисления аргументов фун- кций; они вычисляются
справа налево на PDP-11 и VAX-11 и слева направо на остальных машинах. порядок,
в котором про- исходят побочные эффекты, также не специфицируется.
Так как символьные константы в действительности являются объектами типа INT,
допускается использование символьных констант, состоящих из нескольких символов.
Однако, посколь- ку порядок, в котором символы приписываются к слову, меняет- ся
от машины к машине, конкретная реализация оказывается весьма машинно-зависимой.
Присваивание полей к словам и символов к целым осуществ- ляется справо налево
на PDP-11 и VAX-11 и слева направо на других машинах. эти различия незаметны для
изолированных программ, в которых не разрешено смешивать типы (преобразуя, например,
указатель на INT в указатель на CHAR и затем про- веряя указываемую память), но
должны учитываться при согла- совании с накладываемыми извне схемами памяти.
Язык, принятый на различных компиляторах, отличается только незначительными деталями.
Самое заметное отличие сос- тоит в том, что используемый в настоящее время компилятор
на PDP-11 не инициализирует структуры, которые содержат поля битов, и не допускает
некоторые операции присваивания в оп- ределенных контекстах, связанных с использованием
значения присваивания.
25. Анахронизмы
Так как язык "C" является развивающимся языком, в старых программах можно встретить
некоторые устаревшие конструкции. Хотя большинство версий компилятора поддерживает
такие анах- ронизмы, они в конце концов исчезнут, оставив за собой толь- ко проблемы
переносимости.
В ранних версиях "C" для проблем присваивания использо- валась форма =ON, а не
ON=, приводя к двусмысленностям, ти- пичным примером которых является
X = -1
где X фактически уменьшается, поскольку операции = и - при- мыкают друг к другу,
но что вполне могло рассматриваться и как присваивание -1 к X.
Синтаксис инициализаторов изменился: раньше знак равенс- тва, с которого начинается
инициализатор, отсутствовал, так что вместо
INT X = 1;
использовалось
INT X 1;
изменение было внесено из-за инициализации
INT F (1+2)
которая достаточно сильно напоминает определение функции, чтобы смутить компиляторы.
26. Сводка синтаксических правил
Эта сводка синтаксиса языка "C" предназначена скорее для облегчения понимания
и не является точной формулировкой язы- ка.
26.1. Выражения
Основными выражениями являются следующие:
выражение:
первичное-выражение
* выражение
& выражение
- выражение
! Выражение
\^ выражение
++ L-значение
-- L-значение
L-значение ++
L-значение --
SIZEOF выражение
(имя типа) выражение
выражение бинарная-операция выражение
выражение ? Выражение : выражение
L-значение операция-присваивания выражение
выражение , выражение
первичное выражение:
идентификатор
константа
строка
(выражение)
первичное-выражение (список выражений
необ)
первичное-выражение [выражение]
L-значение . Идентификатор
первичное выражение -> идентификатор
L-значение:
идентификатор
первичное-выражение [выражение]
L-значение . Идентификатор
первичное-выражение -> идентификатор
* выражение
(L-значение)
Операции первичных выражений
() [] . ->
имеют самый высокий приоритет и группируются слева направо. Унарные операции
* & - ! \^ ++ -- SIZEOF(Имя типа)
имеют более низкий приоритет, чем операции первичных выраже- ний, но более высокий,
чем приоритет любой бинарной опера- ции. Эти операции группируются справа налево.
Все бинарные операции и условная операция (прим. Перевод.: условная опе- рация группируется
справа налево; это изменение внесено в язык в 1978 г.) группируются слева направо
и их приоритет убывает в следующем порядке:
Бинарные операции:
* / %
+ -
>> <<
< > <= >=
== !=
&
\^
\!
&&
\!\!
?:
Все операции присваивания имеют одинаковый приоритет и груп- пируются справа
налево. Операции присваивания:
= += -= *= ?= %= >>= <<= &= \^= \!=
Операция запятая имеет самый низкий приоритет и группируется слева направо.
26.2. Описания
Описание: спецификаторы-описания список-инициализируемых-описателей
необ;
спецификаторы-описания:
спецификатор-типа спецификаторы-описания
необ
спецификатор-класса-памяти спецификаторы-описания
необ спецификатор-класса-памяти:
AUTO
STATIC
EXTERN
REGISTER
TYPEDEF спецификатор-типа:
CHAR
SHORT
INT
LONG
UNSIGNED
FLOAT
DOUBLE
спецификатор-структуры-или-объединения
определяющее-тип-имя список-инициализируемых-описателей:
инициализируемый-описатель
инициализируемый-описатель,
список-инициализируемых-описателей инициализируемый-описатель
описатель-инициализатор
необ описатель:
идентификатор
(описатель)
* описатель
описатель ()
описатель [константное выражение
необ]
спецификатор-структуры-или-объединения:
STRUCT список-описателей-структуры
STRUCT идентификатор \(список-описаний-структуры\)
STRUCT идентификатор
UNION \(список-описаний-структуры\)
UNION идентификатор \(список-описаний-структуры\)
UNION идентификатор список-описаний-структцры:
описание-структуры
описание-структуры список-описаний-структуры описание структуры:
спецификатор-типа список-описателей-структуры: список-описателей-структуры
описатель-структуры
описатель-структуры,список-описателей-структуры описатель-структуры:
описатель
описатель: константное выражение
:константное-выражение инициализатор:
= выражение
= \(список-инициализатора\)
= \(список-инициализатора\) список инициализатора:
выражение
список-инициализатора,список-инициализатора
\(список-инициализатора\) имя-типа:
спецификатор-типа абстрактный-описатель абстрактный-описатель:
пусто
\(абстрактный-описатель\)
* абстрактный-описатель
абстрактный-описатель ()
абстрактный-описатель [константное-выражение
необ] определяющее-тип-имя:
идентификатор
26.3. Операторы
составной-оператор:
\(список-описаний список-операторов
необ необ\) список-описаний:
описание
описание список-описаний список-операторов:
оператор
оператор список-операторов оператор:
составной оператор
выражение;
IF (выражение) оператор
IF (выражение) оператор ELSE оператор
WHILE (выражение) оператор
DO оператор WHILE (выражение);
FOR(выражение-1 ;выражение-2 ;выражение-3 )
необ необ необ
оператор
SWITCH (выражение) оператор
CASE константное-выражение : оператор
DEFAULT: оператор
BREAK;
CONTINUE;
RETURN;
RETURN выражение;
GOTO идентификатор;
идентификатор : оператор
;
26.4. Внешние определения
Программа:
внешнее-определение
внешнее-определение программа внешнее-определение:
определение-функции
определение-данных определение-функции:
спецификатор-типа описатель-функции тело-функции
необ описатель-функции:
описатель (список-параметров )
необ список-параметров:
идетификатор
идентификатор , список-параметров тело-функции:
список-описаний-типа оператор-функции оператор-функции:
\(список описаний список-операторов\)
необ определение данных:
EXTERN спецификатор типа список
необ необ
инициализируемых описателей ;
необ
STATIC спецификатор типа список
необ необ
инициализируемых описателей
необ;
26.5. Препроцессор
#DEFINE идентификатор строка-лексем #DEFINE #DEFINE идентификатор(идентификатор,...,идентификатор)стр
#UNDEF идентификатор #INCLUDE "имя-файла" #INCLUDE <имя-файла> #IF константное-выражение
#IFDEF идентификатор #IFNDEF идентификатор #ELSE #ENDIF #LINE константа идентификатор
Последние изменения языка "C" (15 ноября 1978 г.)
27. Присваивание структуры
Структуры могут быть присвоены, переданы функциям в ка- честве аргументов и возвращены
функциям. Типы участвующих операндов должны оставаться теми же самыми. Другие правдопо-
добные операторы, такие как сравнение на равенство, не были реализованы.
В реализации возвращения структур функциями на PDP-11 имеется коварный дефект:
если во время возврата происходит прерывание и та же самая функция пеентерабельно
вызывается во время этого прерывания, то значение возвращаемое из пер- вого вызова,
может быть испорчено. Эта трудность может воз- никнуть только при наличии истинного
прерывания, как из опе- рационной системы, так и из программы пользователя, прерыва-
ния, которое существенно для использования сигналов; обычные рекурсивные вызовы
совершенно безопасны.
28. Тип перечисления
Введен новый тип данных,аналогичный скалярным типам язы- ка паскаль. К спецификатору-типа
в его синтаксическом описа- нии в разделе 8.2. Приложения а следует добавить
спецификатор-перечисления
с синтаксисом
пецификатор-перечисления:
ENUM список-перечисления ENUM идентификатор список-перечисления
------------- ------------------- ENUM идентификатор
cписок-перечисления: перечисляемое список-перечисления, перечисляемое
------------------- ------------- перечисляемое:
идентификатор
идентификатор = константное выражение
------------- ---------------------
Роль идентификатора в спецификаторе-перечисления пол- ностью аналогична роли
ярлыка структуры в спецификато- ре-структуры; идентификатор обозначает определенное
перечис- ление. Например, описание
ENUM COLOR \(RED, WHITE, BLACK, BLUE \);
. . .
ENUM COLOR *CP, COL;
Объявляет идентификатор COLOR ярлыком перечисления типа, описывающего различные
цвета и затем объявляет CP указателем на объект этого типа, а COL - объектом этого
типа.
Идентификаторы в списке-перечисления описываются как константы и могут появиться
там, где требуются (по контекс- ту) константы. Если не используется вторая форма
перечисляе- мого (с равеством =), то величины констант начинаются с 0 и возрастают
на 1 в соответствии с прочтением их описания сле- ва на право. Перечисляемое с присвоением
= придает соответс- твующему идентификатору указанную величину; последующие идентификаторы
продолжают прогрессию от приписанной величи- ны.
Все ярлыки перечисления и константы могут быть различны- ми и непохожими на ярлыки
и члены структур даже при условии использования одного и того же множества идентификаторов.
Объекты данного типа перечисления рассматриваются как объекты, имеющие тип, отличный
от любых типов и контролирую- щая программа LINT сообщает об ошибках несоответствия
типов. В реализации на PDP-11 со всеми перечисляемыми переменными оперируют так,
как если бы они имели тип INT.
29. Таблица изображений непечатных символов языка "C".
В данной таблице приведены изображения некоторых симво- лов (фигурные скобки
и т.д.) языка "C", которых может не оказаться в знаковом наборе дисплея или печатающего
устройс- тва.
! Значение ! Изображение ** ! ! ! В тексте ! ! Фигурная открывающаяся !
! ! Скобка ! \( ! ! ! ! ! Фигурная закрывающаяся ! ! ! Скобка ! \) ! ! ! !
! Вертикальная ! ! ! Черта ! \! ! ! ! ! ! ! ! ! Апостороф ! \' ! ! ! !
! Волнистая ! ! ! Черта ! \^ ! ! ! !