С момента публикации первого издания этой книги определение языка Си претерпело изменения. Почти все нововведения — это расширения исходной версии языка, выполненные так, чтобы сохранилась совместимость с существующими программами; некоторые изменения касаются устранения двусмысленностей первоначального описания, а некоторые представляют собой модификации, привнесенные существующей практикой. Многие из новых возможностей, впоследствии принятые другими разработчиками Си-компиляторов, были первоначально объявлены в документах, прилагаемых к компиляторам. Комитет 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
могут иметь любой
целочисленный тип.