| Ошибка в разделе "2.6. Операции отношения и логические операции"? |
Справочное руководство по языку C
9.16. Соображения о переносимости
Некоторые части языка "C" по своей сути машинно-зависимы. Следующие ниже перечисление потенциальных трудностей хотя и не являются всеобъемлющими, но выделяет основные из них.
Как показала практика, вопросы, целиком связанные с аппаратным оборудованием, такие как размер слова, свойства плавающей арифметики и целого деления, не представляют особенных затруднений. Другие аспекты аппаратных средств находят свое отражение в различных реализациях. Некоторые из них, в частности, знаковое расширение (преобразующее отрицательный символ в отрицательное целое) и порядок, в котором помещаются байты в слове, представляют собой неприятность, которая должна тщательно отслеживаться. Большинство из остальных проблем этого типа не вызывает сколько-нибудь значительных затруднений.
Число переменных типа register, которое фактически может быть помещено в регистры, меняется от машины к машине, также как и набор допустимых для них типов. Тем не менее все компиляторы на своих машинах работают надлежащим образом; лишние или недопустимые регистровые описания игнорируются.
Некоторые трудности возникают только при использовании сомнительной практики программирования. Писать программы, которые зависят от каких-либо этих свойств, является чрезвычайно неразумным.
Языком не указывается порядок вычисления аргументов функций ; они вычисляются справа налево на PDP-11 и VAX-11 и слева направо на остальных машинах. порядок, в котором происходят побочные эффекты, также не специфицируется.
Так как символьные константы в действительности являются объектами типа int, допускается использование символьных констант, состоящих из нескольких символов. Однако, поскольку порядок, в котором символы приписываются к слову, меняется от машины к машине, конкретная реализация оказывается весьма машинно-зависимой.
Присваивание полей к словам и символов к целым осуществляется справа налево на PDP-11 и VAX-11 и слева направо на других машинах. Эти различия незаметны для изолированных программ, в которых не разрешено смешивать типы (преобразуя, например, указатель на int в указатель на char и затем проверяя указываемую память), но должны учитываться при согласовании с накладываемыми извне схемами памяти.
Язык, принятый на различных компиляторах, отличается только незначительными деталями. Самое заметное отличие состоит в том, что используемый в настоящее время компилятор на PDP-11 не инициализирует структуры, которые содержат поля битов, и не допускает некоторые операции присваивания в определеных контекстах, связанных с использованием значения присваивания.
9.17. Анахронизмы
Так как язык "C" является развивающимся языком, в старых программах можно встретить некоторые устаревшие конструкции. Хотя большинство версий компилятора поддерживает такие анахронизмы, они в конце концов исчезнут, оставив за собой только проблемы переносимости.
В ранних версиях "C" для проблем присваивания использовалась форма =on, а не on=, приводя к двусмысленностям, типичным примером которых является
x = -1
где x фактически уменьшается, поскольку операции = и - примыкают друг к другу, но что вполне могло рассматриваться и как присваивание -1 к x.
Синтаксис инициализаторов изменился: раньше знак равенства, с которого начинается инициализатор, отсутствовал, так что вместо
int x = 1;
использовалось
int x 1;
изменение было внесено из-за инициализации
int f (1+2)
которая достаточно сильно напоминает определение функции, чтобы смутить компиляторы.
9.18. Сводка синтаксических правил
Эта сводка синтаксиса языка "C" предназначена скорее для облегчения понимания и не является точной формулировкой языка.
9.18.1. Выражения
Основными выражениями являются следующие:
выражение:
первичное-выражение
* выражение
& выражение
- выражение
! Выражение
^ выражение
++ l-значение
-- l-значение
l-значение ++
l-значение --
sizeof выражение
(имя типа) выражение
выражение бинарная-операция выражение
выражение ? Выражение : выражение
l-значение операция-присваивания выражение
выражение , выражение
первичное выражение:
идентификатор
константа
строка
(выражение)
первичное-выражение (список выражений
необ)
первичное-выражение [выражение]
l-значение . Идентификатор
первичное выражение -> идентификатор
l-значение:
идентификатор
первичное-выражение [выражение]
l-значение . Идентификатор
первичное-выражение -> идентификатор
* выражение
(l-значение)Операции первичных выражений
() [] . ->
имеют самый высокий приоритет и группируются слева направо. Унарные операции
* & - ! ~ ++ -- sizeof(Имя типа)
имеют более низкий приоритет, чем операции первичных выражений, но более высокий, чем приоритет любой бинарной операции. Эти операции группируются справа налево. Все бинарные операции и условная операция (прим. перевод.: условная операция группируется справа налево; это изменение внесено в язык в 1978 г.) группируются слева направо и их приоритет убывает в следующем порядке:
Бинарные операции:
- * / %
- + -
- >> <<
- < > <= >=
- == !=
- &
- ~
- |
- &&
- ||
- ?:
Все операции присваивания имеют одинаковый приоритет и группируются справа налево. Операции присваивания:
= += -= *= ?= %= >>= <<= &= ~ = |=
Операция запятая имеет самый низкий приоритет и группируется слева направо.
9.18.2. Описания
Описание:
спецификаторы-описания список-инициализируемых-описателей
необ;
---------------------------------------------------------
спецификаторы-описания:
спецификатор-типа спецификаторы-описания
необ
спецификатор-класса-памяти спецификаторы-описания
необ
спецификатор-класса-памяти:
auto
static
extern
register
typedef
спецификатор-типа:
char
short
int
long
unsigned
float
double
спецификатор-структуры-или-объединения
определяющее-тип-имя
список-инициализируемых-описателей:
инициализируемый-описатель
инициализируемый-описатель,
список-инициализируемых-описателей
инициализируемый-описатель
описатель-инициализатор
необ
описатель:
идентификатор
(описатель)
* описатель
описатель ()
описатель [константное выражение
необ]спецификатор-структуры-или-объединения:
struct список-описателей-структуры
struct идентификатор {список-описаний-структуры}
struct идентификатор
union {список-описаний-структуры}
union идентификатор {список-описаний-структуры}
union идентификатор
список-описаний-структуры:
описание-структуры
описание-структуры список-описаний-структуры
описание структуры:
спецификатор-типа список-описателей-структуры:
список-описателей-структуры
описатель-структуры
описатель-структуры,список-описателей-структуры
описатель-структуры:
описатель
описатель: константное выражение
:константное-выражение
инициализатор:
= выражение
= {список-инициализатора}
= {список-инициализатора}
список инициализатора:
выражение
список-инициализатора,список-инициализатора
{список-инициализатора}
имя-типа:
спецификатор-типа абстрактный-описатель
абстрактный-описатель:
пусто
{абстрактный-описатель}
* абстрактный-описатель
абстрактный-описатель ()
абстрактный-описатель [константное-выражение
необ]
определяющее-тип-имя:
идентификатор9.18.3. Операторы
составной-оператор:
{список-описаний список-операторов
необ необ}
список-описаний:
описание
описание список-описаний
список-операторов:
оператор
оператор список-операторов
оператор:
составной оператор
выражение;if (выражение) оператор
if (выражение) оператор else оператор
while (выражение) оператор
do оператор while (выражение);
for(выражение-1 ;выражение-2 ;выражение-3 )
необ необ необ
оператор
switch (выражение) оператор
case константное-выражение : оператор
default: оператор
break;
continue;
return;
return выражение;
goto идентификатор;
идентификатор : оператор
;9.18.4. Внешние определения
Программа:
внешнее-определение
внешнее-определение программа
внешнее-определение:
определение-функции
определение-данных
определение-функции:
спецификатор-типа описатель-функции тело-функции
необ
описатель-функции:
описатель (список-параметров)
необ
список-параметров:
идетификатор
идентификатор , список-параметров
тело-функции:
список-описаний-типа оператор-функции
оператор-функции:
{список описаний список-операторов}
необ
определение данных:
extern спецификатор типа список
необ необ
инициализируемых описателей ;
необ
static спецификатор типа список
необ необ
инициализируемых описателей
необ;9.18.5. Препроцессор
#define идентификатор строка-лексем #define #define идентификатор(идентификатор,...,идентификатор)стр #undef идентификатор #include "имя-файла" #include <имя-файла> #if константное-выражение #ifdef идентификатор #ifndef идентификатор #else #endif #line константа идентификатор
Последние изменения языка "C" (15 ноября 1978 г.)