Приложение C. Перечень изменений
С момента публикации первого издания этой книги определение языка Си претерпело изменения. Почти все нововведения — это расширения исходной версии языка, выполненные так, чтобы сохранилась совместимость с существующими программами; некоторые изменения касаются устранения двусмысленностей первоначального описания, а некоторые представляют собой модификации, привнесенные существующей практикой Многие из новых возможностей, впоследствии принятые другими разработчиками Си-компиляторов, были первоначально объявлены в документах, прилагаемых к компиляторам. Комитет ANSI, подготавливая стандарт языка, включил большинство этих изменений, а также ввел другие значительные модификации. Некоторые коммерческие компиляторы реализовали их еще до выпуска официального стандарта языка Си.
В этом приложении сведены воедино различия между языком, определенным в первой его редакции, и той его версии, которая принята в качестве стандарта. Здесь рассматривается только сам язык; вопросы, относящиеся к его окружению и библиотеке, не затрагиваются. Хотя последние и являются важной частью стандарта, но, поскольку в первом издании не делалось попытки описать среду и библиотеку, с соответствующими стандартными элементами сравнивать практически нечего.
- В стандарте более тщательно, по сравнению с первым изданием, определено и расширено препроцессирование: в его основу явно положены лексемы; введены новые операторы для конкатенации лексем (##) и создания символьных строк (#), а также новые директивы, такие как #elif и #pragma; разрешено повторное определение макроса с той же последовательностью лексем; отменена подстановка параметров внутри строк. Разрешено «склеивание» строк с помощью знака \ в любом месте, а не только в строках и макроопределениях (см. А12).
- Минимальное число значимых символов всех внутренних идентификаторов доведено до 31; для идентификаторов с внешней связью оно остается равным 6; буквы нижнего и верхнего регистров не различаются. (Многие реализации допускают большее число значимых символов.)
- Для знаков #, \, X, [, ], {, }, |, D, которых может не быть в некоторых наборах символов, введены трехзнаковые последовательности, начинающиеся с ?? (см. А12.1). Следует заметить, что введение трехзнаковых последовательностей может повредить значения строк, в которых содержатся ??.
- Введены новые ключевые слова (void, const, volatile, signed, enum), а мертворожденное слово entry из обращения изъято.
- Для символьных констант и строковых литералов определены новые управляющие последовательности. Объявлено, что появление за \ символов не из принятых управляющих последовательностей приводит к непредсказуемому результату (см. А2.5.2.).
- Узаконено полюбившееся всем тривиальное изменение: 8 и 9 не являются восьмеричными цифрами.
- Введен расширенный набор суффиксов для явного указания типов констант: U и L — для целых и F и L — для типов с плавающей точкой. Уточнены также правила определения типа для констант без суффиксов (А2.5).
- Объявлено, что соседние строки конкатенируются.
- Предоставлены средства, позволяющие записывать строковые литералы и символьные константы из расширенного набора символов (А2.6).
- Объекты типа char (как и объекты другого типа) можно специфицировать явно со знаком или без знака. Исключается использование словосочетания long float в смысле double, но вводится тип long double для чисел с плавающей точкой повышенной точности.
- С некоторых пор доступен тип unsigned char. Стандарт вводит ключевое слово signed для явного указания, что объект типа char или другого целочисленного типа имеет знак.
- Уже несколько лет в большинстве реализаций доступен тип void. Стандарт вводит void * в качестве типа обобщенного указателя; раньше для этой цели использовали char *. Одновременно вступают в силу правила, по которым запрещается без преобразования типа «смешивать» указатели и целые или указатели разных типов.
- Стандарт устанавливает минимальные пределы диапазонов арифметических типов, предусматривает заголовочные файлы <limits.h> и <float.h>, в которых помещаются эти характеристики для каждой конкретной реализации.
- Перечисление — новый тип, которого не было в первой редакции.
- Стандарт заимствует из Си++ способ записи квалификатора типа, в частности квалификатора const (A8.2).
- Вводится запрет на модификацию строк; это значит, что их разрешается размещать в памяти, доступной только на чтение (ПЗУ).
- Изменены «обычные арифметические преобразования»; по существу, выполнен переход от принципа «для целых всегда превалирует unsigned; для плавающей точки всегда используется double» к принципу «повышение до минимального достаточно вместительного типа» (см. А6.5).
- Отменены старые операторы присваивания вроде =+. Каждый оператор присваивания теперь представляется одной отдельной лексемой. В первом издании оператор присваивания мог изображаться парой символов, возможно, разделенных символами-разделителями.
- Компиляторам более не разрешается трактовать математическую ассоциативность операторов как вычислительную ассоциативность.
- Введен унарный оператор + для симметрии с унарным -.
- Разрешено использовать указатель на функцию в качестве ее именующего выражения без явного оператора * (см. А7.3.2).
- Структурами разрешено оперировать при присваиваниях, можно передавать структуры в качестве аргументов функциям и получать их в качестве результата от функций.
- Разрешено применять оператор получения адреса & к массиву; результатом является указатель на массив.
- В первой редакции результат операции sizeof имел тип int; во многих реализациях он заменен на unsigned. Стандарт официально объявляет его зависимым от реализации, но требует, чтобы он был определен в заголовочном файле <stddef.h> под именем size_t. Аналогичное изменение было сделано в отношении типа разности указателей, который теперь выступает под именем ptrdiff_t (см. А7.4.8 и А7.7).
- Запрещено применять оператор получения адреса & к объекту типа register даже тогда, когда компилятор не располагает его в регистре.
- Типом результата операции сдвига является тип ее левого операнда; тип правого операнда на повышение типа результата влияния не оказывает (см. А7.8).
- Стандарт разрешает адресоваться с помощью указателей на место, лежащее сразу за последним элементом массива, и позволяет оперировать с такими указателями, как с обычными, см. А7.7.
- Стандарт вводит (заимствованный из Си++) способ записи прототипа функции с включением в него типов параметров и явного указания о возможности их изменения и формализует метод работы с переменным списком аргументов (cм. А7.3.2, А8.6.3, В7). С некоторыми ограничениями доступен и старый способ записи.
- Стандартом запрещены пустые объявления, т.е. такие, в которых нет объявителей и не объявляется ни одной структуры, объединения или перечисления. Однако объявление с одним тегом структуры (или объединения) переобъявит ее даже в том случае, если она была объявлена во внешней области действия.
- Запрещены объявления внешних данных, не имеющие спецификаторов и квалификаторов (т.е. объявления с одним «голым» объявителем).
- В некоторых реализациях, когда объявление extern расположено во внутреннем блоке, его область видимости распространяется на остальную часть файла. Стандарт вносит ясность в эту ситуацию и объявляет, что область видимости такого объявления ограничена блоком.
- Область видимости параметров «вставляется» в составную инструкцию, представляющую собой тело функции, так что объявления на верхнем уровне функции не могут их «затенить».
- Несколько изменены именные пространства идентификаторов. Всем тегам структур, объединений и перечислений стандарт выделяет одно именное пространство; для меток инструкций вводится отдельное именное пространство (см. А11.1). Кроме того, имена элементов связаны со структурой или объединением, частью которого они являются. (С некоторых пор это общепринятая практика.)
- Допускается инициализация объединения; инициализатор относится к первому элементу объединения.
- Разрешается инициализация автоматических структур, объединений и массивов, хотя и с некоторыми ограничениями.
- Разрешается инициализация массива символов с помощью строкового литерала по точному количеству указанных символов (без '\0').
- Управляющее выражение и метки ветвей case в инструкции switch могут иметь любой целочисленный тип.
Сайт управляется системой
uCoz