Опубликован: 05.07.2006 | Доступ: свободный | Студентов: 4580 / 871 | Оценка: 4.12 / 3.74 | Длительность: 18:59:00
Лекция 10:

Справочное руководство по языку C

< Лекция 9 || Лекция 10: 1234567891011

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 г.)

< Лекция 9 || Лекция 10: 1234567891011
Николай Макаров
Николай Макаров
Россия, Ульяновск