С момента публикации первого издания этой книги определение языка Си претерпело изменения. Почти все нововведения — это расширения исходной версии языка, выполненные так, чтобы сохранилась совместимость с существующими программами; некоторые изменения касаются устранения двусмысленностей первоначального описания, а некоторые представляют собой модификации, привнесенные существующей практикой. Многие из новых возможностей, впоследствии принятые другими разработчиками Си-компиляторов, были первоначально объявлены в документах, прилагаемых к компиляторам. Комитет ANSI, подготавливая стандарт языка, включил большинство этих изменений, а также ввел другие значительные модификации. Некоторые коммерческие компиляторы реализовали их еще до выпуска официального Си-стандарта.
В этом приложении сведены воедино различия между языком, определенном в первой редакции, и той его версии, которая принята в качестве стандарта. Здесь рассматривается только сам язык, вопросы, относящиеся к его окружению и библиотеке не затрагиваются. Хотя последние и являются важной частью стандарта, но, поскольку в первом издании не делалось попытки описать окружение и библиотеку, сравнить их с соответствующими стандартными элементами оказывается невозможным.
##) и создания стрингов (#), а также
новые управляющие строки типа #elif и #pragma; разрешено повторное
определение макроса с той же последовательностью лексем; отменена подстановка
параметров внутри стрингов. Разрешено склеивание строк при помощи \ в любом
месте, но только не в стрингах и макроопределениях.
# \ ^ [ ] { } | ~, которых может не быть в некоторых наборах
литер, введены трехзнаковые последовательности, начинающиеся с ?? (См.
A12.1). Следует заметить, что введение трехзнаковых последовательностей может
«испортить» значения стрингов, в которых содержатся ??.
void, const, volatile, signed, enum), а
мертворожденное слово entry из обращения изъято.
\ «неправильных» литер
приводит к непредсказуемому результату (См. A2.5.2.)
U и
L — для целых и F и L — для плавающих. Уточнены также правила определения
типа для констант без суффиксов (A2.5).
char (как и объект другого типа) можно специфицировать явно
со знаком или без знака. Исключается использование словосочетания long float
в смысле double, но вводится тип long double для чисел с плавающей точкой
повышенной точности.
unsigned char. Стандарт вводит ключевое слово
signed для явного указания знаковости char и других целочисленных объектов.
void. Стандарт
вводит void * в качестве типа обобщенного указателя; раньше для этой цели
использовали char *. Одновременно вступают в силу правила, по которым
запрещается без преобразования типа «смешивать» указатели и целые или
указатели разных типов.
<limits.h> и <float.h>, в которых
помещаются эти характеристики для каждой конкретной реализации.
const (A8.2).
unsigned; для плавающей точки всегда
используется double» к «повышению до минимального достаточно вместимого
типа». (См. A6.5.)
=+. Каждый оператор
присваивания теперь представляется одной отдельной лексемой. В первом издании
оператор присваивания мог изображаться парой литер, возможно, разделенных
пробельными литерами.
+ для симметрии с унарным -.
*. (См. A7.3.2.)
& к массиву; результатом
будет указатель на массив.
sizeof-операции имел тип int; во многих
реализациях он заменен на unsigned. Стандарт официально объявляет его
реализационно-зависимым, но требует, чтобы он был определен в головном файле
<stddef.h> под именем size_t. Аналогичное изменение было сделано в отношении
типа разности указателей, который теперь выступает под именем ptrdiff_t. (См.
A7.4.8 и A7.7.)
& к register-объекту даже
тогда, когда данный компилятор не располагает его на регистре.
extern-декларация расположена во внутреннем
блоке, ее действие распространяется на остальную часть файла. Стандарт вносит
ясность в эту ситуацию и объявляет, что область действия такой декларации
ограничена блоком.
\0).
case-метки в switch могут иметь любой
целочисленный тип.