
\chapter{Справочное руководство}
\label{apx:ref_manual}

\section{Введение}

Данное руководство является описанием языка программирования Си, определённого в
соответствии с проектом, утверждённым в
\index{American National Standards Institute (ANSI)}%
ANSI в качестве Американского национального стандарта для информационных систем:
Язык программирования Си, X3.159--1989 (<<American National Standard for
Information Systems -- Programming Language C, X3.159--1989>>). Это описание --
лишь некоторый вариант предлагаемого стандарта, а не сам стандарт, однако мы
специально заботились о том, чтобы оно было надёжным руководством по языку.

Настоящий документ в основном следует общей схеме описания, принятой в стандарте
(публикация которого в свою очередь основывалась на первом издании этой книги),
однако в организационном плане есть различия. Если не считать отклонений в
названиях нескольких продукций и отсутствия формальных определений лексем и
препроцессора, грамматики языка здесь и в стандарте эквивалентны.

\begin{ApxComment}
Далее всюду примечания (как и это) набираются с отступом от левого края
страницы. В основном эти примечания касаются отличий стандарта от версии языка,
описанной в первом издании этой книги‚ и от последующих нововведений в различных
компиляторах.
\end{ApxComment}

\section{Соглашения о лексике}

\index{лексика, соглашения}%
\index{транслируемая компонента}%
Программа состоит из одной или нескольких \emph{компонент трансляции},
хранящихся в виде файлов.
\index{трансляция!фазы}%
\index{фазы трансляции}%
Каждая такая компонента проходит ряд фаз трансляции, описанных
в~\ref{apx:sec:preprocessing}. Начальные фазы осуществляют лексические
преобразования нижнего уровня, выполняют директивы, задаваемые в программе
строками, начинающимися со знака \verb|#|, обрабатывают макроопределения и
получают макрорасширения. По завершению
препроцессирования~(\ref{apx:sec:preprocessing}) программа представляется в виде
последовательности лексем.

\subsection{Лексемы}

\index{лексема}%
Существуют шесть классов лексем: идентификаторы, ключевые слова, константы,
стринговые литералы, операторы и прочие разделители.
\index{литера!новая-строка \texttt{\textbackslash n}}%
\index{литеры!пробельные}%
\index{пробельные литеры}%
\index{n@\texttt{\textbackslash n}}%
Пробелы, горизонтальные и вертикальные табуляции, новые-строки,
переводы-страницы и
\index{комментарий}%
комментарии (имеющие общее название <<пробельные литеры>>) рассматриваются
компилятором только как разделители лексем и в остальном на результат трансляции
влияния не оказывают.
\index{отступы в тексте программы}%
\index{программа!формат}%
Любая из пробельных литер годится, чтобы отделить друг от друга соседние
идентификаторы, ключевые слова и константы.

Если предположить, что входной поток уже до некоторой литеры разбит на лексемы,
то следующей лексемой будет самый длинный стринг, который вообще может быть
лексемой.

\subsection{Комментарий}

\index{комментарий}%
Литеры \verb|/*| открывают комментарий, а литеры \verb|*/| закрывают его.
Комментарии нельзя вкладывать друг в друга, их нельзя помещать внутрь стрингов
или текстовых литералов.

\subsection{Идентификаторы}

\index{идентификатор}%
\index{переменная!синтаксис имени}%
\index{синтаксис имён переменных}%
\index{функция!длина имени}%
Идентификатор -- последовательность букв и цифр. Первой литерой должна быть
буква;
\index{литера!подчёркивания \texttt{\_}}%
знак подчёркивания \verb|_| считается буквой. Буквы нижнего и верхнего регистров
различаются.
\index{длина!имени}%
\index{длина!переменной}%
Идентификаторы могут иметь любую длину; для внутренних идентификаторов значимыми
являются первая 31 литера; в некоторых реализациях принято б\'{o}льшее число
значимых литер. К внутренним идентификаторам относятся имена макросов и
\index{имя}%
все другие имена, не имеющие внешних связей~(\ref{apx:subsec:links}).
\index{связь!внешняя}%
На идентификаторы с внешними связями могут накладываться б\'{o}льшие
ограничения: иногда воспринимаются не более шести первых литер и/или не
различаются буквы верхнего и нижнего регистров.

\subsection{Ключевые слова}

\index{ключевые слова}%
\index{список!ключевых слов}%
Следующие идентификаторы зарезервированы в качестве ключевых слов и в другом
смысле использоваться не могут:

\smallskip
{\setlength{\LTleft}{\doubleCodeIndent-\parindent-\tabcolsep}%
\SetLenVarWithVal{\Quarterlen}{(\linewidth-\LTleft-7\tabcolsep-\doubleCodeIndent+\parindent)/4}%
\noindent\hspace{\LTleft}\begin{tabular}
{p{\Quarterlen}p{\Quarterlen}p{\Quarterlen}p{\Quarterlen}}
\verb|auto|    &\verb|double|&\verb|int|     &\verb|struct|  \\
\verb|break|   &\verb|else|  &\verb|long|    &\verb|switch|  \\
\verb|case|    &\verb|enum|  &\verb|register|&\verb|typedef| \\
\verb|char|    &\verb|extern|&\verb|return|  &\verb|union|   \\
\verb|const|   &\verb|float| &\verb|short|   &\verb|unsigned|\\
\verb|continue|&\verb|for|   &\verb|signed|  &\verb|void|    \\
\verb|default| &\verb|goto|  &\verb|sizeof|  &\verb|volatile|\\
\verb|do|      &\verb|if|    &\verb|static|  &\verb|while|
\end{tabular}}
\smallskip

\noindent%
\index{asm@\texttt{asm}}%
\index{fortran@\texttt{fortran}}%
В некоторых реализациях резервируются также слова \verb|fortran| и \verb|asm|.

\begin{ApxComment}
Ключевые слова \verb|const|, \verb|signed| и \verb|volatile| впервые появились в
стандарте ANSI; \verb|enum| и \verb|void| -- новые по отношению к первому
изданию, но уже использовались; ранее зарезервированное \verb|entry| нигде не
использовалось и поэтому более не резервируется.
\end{ApxComment}

\subsection{Константы}
\label{apx:subsec:constants}

\index{константа}%
\index{константа!тип}%
\index{тип!константа}%
Существует несколько видов констант. Каждая имеет свой тип данных; базовые типы
рассматриваются в~\ref{apx:subsec:base_types}.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{константа:}
     \textit{целая-константа}
     \textit{литерная-константа}
     \textit{с-плав-точкой-константа}
     \textit{перечислимая-константа}
\end{ShortGramDecsWithCC}

\subsubsection{Целые константы}

\index{целая константа}%
\index{константа!восьмеричная \texttt{0}\ldots}%
\index{восьмеричная константа \texttt{0}\ldots}%
\index{int@\texttt{int}!константа}%
\index{signed@\texttt{signed}!константа}%
Целая константа, состоящая из последовательности цифр, воспринимается как
восьмеричная, если она начинается с \verb|0| (цифры нуль), и как десятичная в
противном случае. Восьмеричная константа не содержит цифр \verb|8| и \verb|9|.
\index{константа!шестнадцатеричная \texttt{0x}\ldots}%
\index{шестнадцатеричная константа \texttt{0x}\ldots}%
Последовательность цифр, перед которой стоят \verb|0x| или \verb|0X|,
рассматривается как шестнадцатеричное целое. В шестнадцатеричные цифры включены
буквы от \verb|a| (или \verb|A|) до \verb|f| (или \verb|F|) со значениями от
$10$ до $15$.
%
% исправлены орфографические ошибки
% было ``шестнадцатиричное''/''шестнадцатиричные''
%

\index{константа!суффикс}%
\index{суффикс в константе}%
\index{unsigned@\texttt{unsigned}!константа}%
\index{unsigned long, константа@\texttt{unsigned long}, константа}%
Целая константа может быть записана с буквой-суффиксом \verb|u| (или \verb|U|)
для спецификации её как беззнаковой константы.
\index{long@\texttt{long}!константа}%
Она также может быть с буквой-суффиксом \verb|l| (или \verb|L|) для указания,
что она имеет тип \verb|long|.

\index{int@\texttt{int}!константа}%
\index{long@\texttt{long}!константа}%
\index{signed@\texttt{signed}!константа}%
\index{unsigned@\texttt{unsigned}!константа}%
Тип целой константы зависит от её вида, значения и суффикса. (О типах
см.~\ref{apx:sec:what_identificators_mean}.) Если константа -- десятичная и не
имеет суффикса, то она принимает первый из следующих типов, который годится для
представления её значения: \verb|int|, \verb|long int| и
\verb|unsigned long int|. Восьмеричная или шестнадцатеричная константа без
суффикса принимает первый возможный из типов \verb|int|, \verb|unsigned int|,
\verb|long int| и \verb|unsigned long int|. Если константа имеет суффикс
\verb|u| или \verb|U|, то она принимает первый возможный из типов
\verb|unsigned int| и \verb|unsigned long int|. Если константа имеет суффикс
\verb|l| или \verb|L|, то она принимает первый возможный из типов
\verb|long int| и \verb|unsigned long int|.
%
% исправлена орфографическая ошибка
% было ``шестнадцатиричная''
%

\begin{ApxComment}
Типы целых констант получили существенное развитие в сравнении с первой
редакцией, в которой большие целые имели просто тип \verb|long|. Суффиксы
\verb|U| и \verb|u| введены впервые.
\end{ApxComment}

\subsubsection{Литерные константы}
\label{apx:subsubsec:character_constants}

\index{литера!кавычка \texttt{'}}%
\index{константа!литерная}%
\index{char@\texttt{char}!константа}%
Литерная константа -- последовательность из одной или нескольких литер,
заключённая в одиночные кавычки (например, \verb|'x'|). Если внутри одиночных
кавычек расположена одна литера, значением константы является числовое значение
этой литеры в кодировке, принятой на данной машине. Значение константы с
несколькими литерами зависит от реализации.

Литерная константа не может содержать в себе одиночную кавычку <<\verb|'|>> или
литеру новая-строка;
\index{эскейп-последовательность}%
чтобы изобразить их и некоторые другие литеры, могут быть использованы
эскейп-последовательности:

{\setlength{\LTleft}{\codeIndent-\tabcolsep}
\setlength{\LTpre}{\smallskipamount}\setlength{\LTpost}{\smallskipamount}%
\index{таблица!эскейп-последовательностей}%
\begin{longtable}{lll}
новая-строка (\verb|newline|, \verb|linefeed|)%
\index{литера!новая-строка \texttt{\textbackslash n}}%
\index{n@\texttt{\textbackslash n}}%
&\verb|NL (LF)|&\verb|\n|\\
гориз-таб (\verb|horisontal tab|)%
\index{t@\texttt{\textbackslash t}}%
&\verb|HT|     &\verb|\t|\\
верт-таб (\verb|vertical tab|)%
\index{литера!вертикальная табуляция \texttt{\textbackslash v}}%
\index{v@\texttt{\textbackslash v}}%
&\verb|VT|     &\verb|\v|\\
возврат-на-шаг (\verb|backspace|)%
\index{b (backspace)@\texttt{\textbackslash b} (backspace)}%
&\verb|BS|     &\verb|\b|\\
возврат-каретки (\verb|carriage return|)%
\index{литера!возврат каретки \texttt{\textbackslash r}}%
\index{r@\texttt{\textbackslash r}}%
&\verb|CR|     &\verb|\r|\\
перевод-страницы (\verb|formfeed|)%
\index{литера!новая-страница \texttt{\textbackslash f}}%
\index{f литера новая-страница@\texttt{\textbackslash f} литера новая-страница}%
&\verb|FF|     &\verb|\f|\\
сигнал-звонок (\verb|audible alert|,\verb|bell|)%
\index{литера!сигнал-звонок \texttt{\textbackslash a}}%
\index{a@\texttt{\textbackslash a}}%
&\verb|BEL| &\verb|\a|\\
обратная-наклонная-черта (\verb|backslash|)%
\index{литера!обратная наклонная черта \texttt{\textbackslash\textbackslash}}%
&\verb|\|      &\verb|\\|\\
знак-вопроса (\verb|question mark|)           &\verb|?|      &\verb|\?|\\
одиночная-кавычка (\verb|single quote|)%
\index{литера!кавычка \texttt{'}}%
&\verb|'|      &\verb|\'|\\
двойная-кавычка (\verb|double quote|)%
\index{литера!двойная кавычка \texttt{\char`\"}}%
&\verb|"|      &\verb|\"|\\
восьмеричный-код (\verb|octal number|)%
\index{ooo@\texttt{\textbackslash\textit{ooo}}}%
&\textit{\Verb|ooo|}&\verb|\|\textit{\Verb|ooo|}\\
шестнадцатеричный-код (\verb|hex number|)%
\index{xhh шестнадцатеричная эскейп-последовательность@\texttt{\textbackslash x\textit{hh}} шестнадцатеричная эскейп-последовательность}%
&\textit{\Verb|hh|}&\verb|\x|\textit{\Verb|hh|}\\
\end{longtable}}
%
% исправлена орфографическая ошибка
% было ``шестнадцатиричный''
%

\noindent%
\index{константа!литерная!восьмеричная \texttt{\textbackslash\textit{ooo}}}%
\index{эскейп-последовательность!восьмеричная \texttt{\textbackslash\textit{ooo}}}%
Эскейп-последовательность \verb|\|\textit{\Verb|ooo|} состоит из обратной
наклонной черты, за которой следуют одна, две или три восьмеричные цифры,
специфицирующие значение желаемой литеры.
\index{null-литера, 0@null-литера, \texttt{\textbackslash 0}}%
Наиболее частым примером такой конструкции является \verb|\0| (за которой не
следует цифра); она специфицирует null-литеру.
\index{константа!литерная!шестнадцатеричная \texttt{\textbackslash x\textit{hh}}}%
\index{эскейп-последовательность!шестнадцатеричная \texttt{\textbackslash x\textit{hh}}}%
Эскейп-последовательность \verb|\x|\textit{\Verb|hh|} состоит из обратной
наклонной черты с буквой \verb|x|, за которыми следуют шестнадцатеричные цифры,
специфицирующие значение желаемой литеры. На количество цифр нет ограничений, но
результат будет не определён, если значение полученной литеры превысит значение
самой <<большой>> из допустимых литер. Если в данной реализации тип \verb|char|
трактуется как число со знаком, то значение и в восьмеричной, и в
шестнадцатеричной эскейп-последовательности получается при помощи
\index{знак, размножение}%
<<размножения знака>>, как если бы выполнялась операция приведения к типу
\verb|char|. Результат не определён, если за \verb|\| не следует ни одна из
перечисленных выше литер.
%
% исправлены орфографические ошибки
% было ``шестнадцатиричные'' и ``шестнадцатиричной''
%

\index{константа!литерная!из расширенного набора}%
В некоторых реализациях имеется расширенный набор литер, который не может быть
охвачен типом \verb|char|. Константа для такого набора пишется с буквой \verb|L|
впереди (например, \verb|L'x'|) и называется <<широкой>> литерной константой.
\index{wchar{\_}t@\texttt{wchar{\_}}}%
Такая константа имеет тип \verb|wchar_t| (целочисленный тип, определённый в
стандартном головном файле \verb|<stddef.h>|). Как и в случае обычных литерных
констант, здесь также возможны восьмеричные и шестнадцатеричные
эскейп-последовательности; результат будет не определён, если специфицированное
значение превысит тип \verb|wchar_t|.
%
% исправлены орфографические ошибки
% было ``шестнадцатиричные''
%

\begin{ApxComment}
Некоторые из приведённых эскейп-последовательностей новые (шестнадцатеричные в
частности). Новым является и расширенный тип для литер. Наборам литер, обычно
используемым в Америке и Западной Европе, подходит тип \verb|char|, а тип
\verb|wchar_t| был добавлен, главным образом для того, чтобы удовлетворить
азиатские языки.
\end{ApxComment}
%
% исправлены орфографические ошибки
% было ``шестнадцатиричные''
%

\subsubsection{Константы с плавающей точкой (плавающие константы)}

\index{константа!с плавающей точкой}%
\index{константа!суффикс}%
\index{суффикс в константе}%
\index{экспонента в записи числа}%
\index{double@\texttt{double}!константа}%
\index{E (спецификатор экспоненты)@\texttt{E} (спецификатор экспоненты)}%
\index{float@\texttt{float}!константа}%
\index{long double@\texttt{long double}!константа}%
Плавающая константа состоит из целой части, десятичной точки, дробной части,
\verb|e| или \verb|E| и целого (возможно, со знаком), представляющего
экспоненту, и, возможно, типа-суффикса, задаваемого одной из букв: \verb|f|,
\verb|F|, \verb|l| или \verb|L|. И целая, и дробная часть представляют собой
последовательность цифр. Либо целая часть, либо дробная часть (но не обе вместе)
могут отсутствовать; также могут отсутствовать десятичная точка или \verb|E| с
экспонентой (но не обе одновременно). Тип определяется суффиксом; \verb|F| или
\verb|f| определяют тип \verb|float|, \verb|L| или \verb|l| -- тип
\verb|long double|; при отсутствии суффикса подразумевается тип \verb|double|.

\begin{ApxComment}
Суффиксы для плавающих констант являются нововведением.
\end{ApxComment}

\subsubsection{Перечислимые константы}

\index{константа!перечисления}%
\index{перечисление!константа}%
\index{enum@\texttt{enum}!спецификатор}%
Идентификаторы, объявленные как элементы
перечисления~(\ref{apx:subsec:enumerations})‚ являются константами типа
\verb|int|.

\subsection{Стринговые литералы}
\label{apx:subsec:string_literals}

\index{литера!двойная кавычка \texttt{\char`\"}}%
\index{константа!стринговая}%
Стринговый литерал, который также называют стринговой константой, -- это
последовательность литер, заключённая в двойные кавычки (например,
\verb|"..."|). Стринг имеет тип <<массив литер>> и память класса
\verb|static|~(\ref{apx:sec:what_identificators_mean}), которая инициализируется
заданными литерами. Представляются ли одинаковые стринговые литералы одной
копией или несколькими, зависит от реализации. Поведение программы, пытающейся
изменить стринговый литерал, не определено.

\index{конкатенация!стрингов}%
\index{стринг!конкатенация}%
Рядом написанные стринговые литералы объединяются (конкатенируются) в один
стринг. После любой конкатенации к стрингу добавляется \verb|null|-байт
(\verb|\0|), что позволяет программе, просматривающей стринг, найти его конец.
Стринговые литералы не могут содержать в себе новую-строку или двойную кавычку;
в них нужно использовать те же эскейп-последовательности, что и в литерных
константах.

Как и в случае с литерными константами, стринговый литерал с литерами из
расширенного набора должен начинаться с буквы \verb|L| (например,
\verb|L"..."|). Стринговый литерал из расширенного набора имеет тип <<массив из
\verb|wchar_t|>>. Конкатенация обычных и <<расширенных>> стринговых литералов
друг с другом не определена.

\begin{ApxComment}
То, что стринговые литералы не обязательно представляются разными копиями,
запрет на их модификацию, а также конкатенация соседних стринговых литералов
являются нововведениями ANSI-стандарта. <<Расширенные>> стринговые литералы
также объявлены впервые.
\end{ApxComment}

\section{Нотация синтаксиса}

\index{нотация синтаксиса}%
В нотации синтаксиса, используемой в этом руководстве, синтаксические понятия
набираются курсивом, а слова и литеры, воспринимаемые буквально, обычным
шрифтом. Альтернативные конструкции обычно перечисляются в столбик (каждая
альтернатива на отдельной строке); в редких случаях длинные списки небольших по
размеру альтернатив располагаются в одной строке, помеченной словами
<<один из>>. Необязательный терминальный или нетерминальный символ снабжается 
индексом <<\textit{необ}>>. Так, запись

\begin{ShortGramDecsWithCC}{\\\[\]}
{ \textit[выражение]\textsubscript[\textit[необ]] }
\end{ShortGramDecsWithCC}

\noindent обозначает выражение, заключённое в фигурные скобки, которое в общем
случае может отсутствовать. Полный перечень синтаксических конструкций приведён
в~\ref{apx:sec:grammar}.

\begin{ApxComment}
В отличие от грамматики, данной в первом издании этой книги, приведённая здесь
грамматика старшинство и порядок выполнения операций в выражениях описывает
явно.
\end{ApxComment}

\section{Что обозначают идентификаторы}
\label{apx:sec:what_identificators_mean}

\index{перечислитель}%
Существует ряд вещей, на которые ссылаются при помощи идентификаторов, или имён;
это -- функции; теги структур, объединений и перечислений; члены структур или
объединений; \verb|typedef|-имена и объекты.
\index{объект}%
\index{переменная}%
Объектом (называемым иногда переменной) является часть памяти, интерпретация
которой зависит от двух главных характеристик: \emph{класса памяти} и её
\emph{типа}. Класс памяти сообщает о времени жизни памяти, связанной с
идентифицируемым объектом; тип определяет, какого рода значения находятся в
объекте.
\index{область действия}%
С любым именем ассоциируется своя область действия (т.е. тот участок программы,
где это имя <<видимо>>) и
\index{связь}%
\index{связь!внутренняя}%
атрибут связи, определяющий, ссылается ли это имя в другом файле на тот же самый
объект или функцию. Область действия и атрибут связи обсуждаются
в~\ref{apx:sec:scope}.

\subsection{Класс памяти}

\index{память!автоматическая}%
\index{память!статическая}%
\index{память!класс}%
\index{переменная!автоматическая}%
Существуют два класса памяти: автоматический и статический. Несколько ключевых
слов в совокупности с контекстом деклараций объектов специфицируют класс памяти
для этих объектов. Автоматические объекты локализованы в
блоке~(\ref{apx:subsec:composit_instruction})‚ они <<исчезают>> при выходе из
него. Декларация, заданная внутри блока, если в ней отсутствует спецификация
класса памяти или указан спецификатор \verb|auto|, создаёт автоматический
объект. Объект, помеченный в декларации словом \verb|register|, является
автоматическим и размещается по возможности в регистре машины.

\index{переменная!внешняя}%
\index{static-переменные@\texttt{static}-переменные!внешние}%
\index{static-переменные@\texttt{static}-переменные!внутренние}%
Статические объекты могут быть локализованы в блоке или располагаться вне
блоков, но в обоих случаях их значения сохраняются после выхода из блока (или
функции) до повторного в него входа. Внутри блока (в том числе и в блоке,
образующем тело функции) статические объекты в декларациях помечаются словом
\verb|static|. Объекты, декларируемые вне всех блоков на одном уровне с
определениями функций, всегда статические. При помощи ключевого слова
\verb|static| их можно локализовать в пределах транслируемой компоненты (в этом
случае они получают атрибут \emph{внутренней связи}),
\index{связь!внешняя}%
и они становятся глобальными для всей программы, если опустить явное указание
класса памяти или использовать ключевое слово \verb|extern| (в этом случае они
получают атрибут \emph{внешней связи}).

\subsection{Базовые типы}
\label{apx:subsec:base_types}

\index{типы!базовые}%
Существует несколько базовых типов. Стандартный головной файл \verb|<limits.h>|‚
описанный в приложении~\ref{apx:stdlib}, определяет самое большое и самое малое
значения для каждого типа в данной конкретной реализации. В
приложении~\ref{apx:stdlib} приведены минимально возможные величины.

\index{char@\texttt{char}!тип}%
Размер объектов, декларируемых как литеры, позволяет хранить любую литеру из
набора литер, принятого в машине. Если объект типа \verb|char| действительно
хранит литеру из данного набора, то его значением является код этой литеры, т.е.
некоторое неотрицательное целое. Переменные типа \verb|char| могут хранить и
другие значения, но тогда диапазон их значений и особенно вопрос о том, знаковые
эти значения или беззнаковые, зависит от реализации.

\index{литера!знаковая}%
\index{литера!беззнаковая}%
Беззнаковые литеры, декларируемые при помощи слов \verb|unsigned char|, имеют ту
же разрядность, что и обычные литеры, но представляют неотрицательные значения;
при помощи слов \verb|signed char| можно явно декларировать литеры со знаком,
которые занимают столько же места, как и обычные литеры.

\begin{ApxComment}
Тип \verb|unsigned char| не упоминался в первой редакции, но всеми
использовался. Тип \verb|signed char| -- новый.
\end{ApxComment}

\index{типы!целочисленные}%
\index{целочисленные типы}%
\index{int@\texttt{int}!тип}%
\index{long@\texttt{long}!тип}%
\index{short@\texttt{short}}%
\index{signed@\texttt{signed}!тип}%
Помимо \verb|char| среди целочисленных типов могут быть целые трёх размеров:
\verb|short int|, \verb|int| и \verb|long int|. Обычные \verb|int|-объекты
имеют естественный размер, принятый в архитектуре данной машины, другие размеры
предназначены для специальных нужд. Более длинные целые по крайней мере
покрывают все значения более коротких целых, однако в некоторых реализациях
обычные целые могут быть эквивалентны коротким (\verb|short|) или длинным
(\verb|long|) целым. Все типы \verb|int| представляют значения со знаком, если
не оговорено противное.

\index{unsigned@\texttt{unsigned}!тип}%
Для беззнаковых целых в декларациях используется ключевое слово \verb|unsigned|.
Такие целые подчиняются арифметике по модулю $2^n$, где $n$ -- число бит в
представлении числа, и, следовательно, в арифметике с беззнаковыми целыми
никогда не бывает переполнения. Множество неотрицательных значений, которые
могут храниться в знаковых объектах, является подмножеством значений, которые
могут храниться в соответствующих беззнаковых объектах; знаковое и беззнаковое
представления каждого такого значения совпадают.

\index{типы!плавающие}%
Любые два из плавающих типов:
\index{float@\texttt{float}!тип}%
с одинарной точностью (\verb|float|),
\index{double@\texttt{double}!тип}%
с двойной точностью (\verb|double|) и
\index{long double@\texttt{long double}!тип}%
с повышенной точностью (\verb|long double|) могут быть синонимами, но каждый
следующий тип этого списка должен по крайней мере обеспечивать точность
предыдущего.

\begin{ApxComment}
\verb|long double| -- новый тип. В первой редакции синонимом для \verb|double|
был \verb|long float|, теперь последний изъят из обращения.
\end{ApxComment}

\index{перечисление!тип}%
\emph{Перечисления} -- единственные в своём роде типы, которым даётся полный
перечень значений; с каждым перечислением связывается множество именованных
констант~(\ref{apx:subsec:enumerations}). Перечисления ведут себя наподобие
целых, но компилятор обычно выдаёт предупреждающее сообщение, если объекту
некоторого перечислимого типа присваивается нечто, отличное от его константы,
или выражение не этого перечислимого типа.

\index{типы!арифметические}%
Поскольку объекты перечислимых типов можно рассматривать как числа, перечисление
относят к \emph{арифметическому} типу. Типы \verb|char| и \verb|int| всех
размеров, каждый из которых может быть со знаком или без знака, а также
перечислимые типы называют \emph{целочисленными}. Типы \verb|float|,
\verb|double| и \verb|long double| называются \emph{плавающими}.

\index{void@\texttt{void}!тип}%
Тип \verb|void| специфицирует пустое множество значений. Он используется как
<<тип возвращаемого функцией значения>> в том случае, когда она не генерирует
никакого результирующего значения.

\subsection{Выводимые типы}

\index{выводимые типы}%
\index{типы!выводимые}%
Помимо базовых типов существует практически бесконечный класс выводимых типов,
которые формируются из уже существующих и которые описывают следующие
конструкции:

\begin{itemize}
 \item \emph{массивы} объектов заданного типа;
 \item \emph{функции}, возвращающие объекты заданного типа;
 \item \emph{указатели} на объекты заданного типа;
 \item \emph{структуры}, содержащие последовательность объектов, возможно,
 различных заданных типов;
 \item \emph{объединения}, каждое из которых может содержать один из нескольких
 объектов различных заданных типов.
\end{itemize}

В общем случае приведённые методы конструирования объектов могут применяться
рекурсивно.

\subsection{Квалификаторы типов}
\label{apx:subsec:type_qualifiers}

Тип объекта может снабжаться квалификатором.
\index{const@\texttt{const}}%
Декларация объекта с квалификатором \verb|const| указывает на то, что его
значение далее не будет изменяться;
\index{volatile@\texttt{volatile}}%
объявляя объект как \verb|volatile| (изменчивый, непостоянный (\textit{англ.}))
мы указываем на его особые свойства в отношении оптимизации, выполняемой
компилятором. Ни один из квалификаторов не влияет на диапазоны значений и
арифметические свойства объектов. Квалификаторы обсуждаются
в~\ref{apx:subsec:type_specifiers}.

\section{Объекты и l-значения}
\label{apx:sec:objects_and_lvalues}

\index{объект}%
\emph{Объект} -- это некоторая именованная область памяти;
\index{l-значение}%
\emph{l-значение} -- выражение, ссылающееся на объект. Очевидным примером
l-значения является идентификатор с соответствующим типом и классом памяти.
Существуют операции, порождающие l-значения. Например, если \verb|E| --
выражение типа указатель, то \verb|*E| есть выражение для l-значения,
ссылающегося на объект, на который указывает \verb|E|. Термин <<l-значение>>
произошёл от записи присваивания \verb|E1 = E2|, в которой левый (left -- левый
(\textit{англ.}), отсюда и буква l) операнд \verb|E1| должен быть выражением
l-значения. Описывая каждый оператор, мы сообщаем, ожидает ли он l-значения в
качестве операндов и выдаёт ли l-значение в качестве результата.

\section{Преобразования}
\label{apx:sec:type_conversion}

\index{оператор!приведения к типу|(}%
\index{преобразование|(}%
\index{приведение к типу|(}%
\index{преобразование!оператором приведения}%
\index{тип!правила преобразования|(}%
Некоторые операторы в зависимости от своих операндов могут вызывать
преобразование их значений из одного типа в другой. В этом разделе объясняется,
что следует ожидать от таких преобразований.
В~\ref{apx:subsec:arifmetic_conversion} формулируются правила, по которым
выполняются преобразования для большинства обычных операторов. Эти правила могут
уточняться при рассмотрении каждого отдельного оператора.

\subsection{Повышение целочисленного типа}
\label{apx:subsec:integral_promotion}

\index{переполнение|(}%
\index{повышение!целочисленного типа}%
\index{преобразование!литера -- целое}%
\index{целочисленное повышение}%
Объект перечислимого типа, литера, короткое целое, целое в поле бит -- все они
со знаком или без могут использоваться в выражении там, где возможно применение
целого. Если тип \verb|int| позволяет <<охватить>> все значения исходного типа
операнда, то операнд приводится к \verb|int|, в противном случае он приводится к
\verb|unsigned int|. Эта процедура называется \emph{повышением целочисленности}.

\subsection{Целочисленные преобразования}

\index{преобразование!целое -- литера}%
Любое целое приводится к некоторому заданному беззнаковому типу путём поиска
конгруэнтного (т.е. имеющего то же двоичное представление) наименьшего
неотрицательного значения и взятия его по модулю $n_{max}+1$, где $n_{max}$ --
наибольшее число в этом беззнаковом типе. Для двоичного представления в
дополнительном коде это означает либо выбрасывание лишних старших разрядов, если
беззнаковый тип <<\'{y}же>> исходного типа, либо заполнение недостающих старших
разрядов нулями (для значения без знака) или размноженным знаком (для значения
со знаком), если беззнаковый тип <<шире>> исходного.
%
% исправлена орфографическая ошибка
% в оригинале было ``конгруентного''
%

В результате приведения любого целого к знаковому типу преобразуемое значение не
меняется, если оно представимо в новом типе, в противном случае результат
зависит от реализации.

\subsection{Целые и плавающие}

\index{обрезание!значения с плавающей точкой}%
\index{преобразование!плавающее -- целое}%
\index{преобразование!целое -- плавающее}%
При преобразовании из плавающего типа в целый дробная часть значения
отбрасывается; если полученное при этом значение нельзя представить в заданном
целом типе, то результат не определён. В частности, не определён результат
преобразования отрицательных плавающих значений в беззнаковые целые.

Если значение преобразуется из целого в величину с плавающей точкой и она
находится в допустимом диапазоне, но представляется в новом типе неточно, то
результатом будет одно из двух значений нового типа, ближайшего к исходному.
Если результат выходит за границы диапазона допустимых значений, поведение
программы не определено.

\subsection{Плавающие типы}

\index{преобразование!\texttt{double} -- \texttt{float}}%
\index{преобразование!\texttt{float} -- \texttt{double}}%
При преобразовании из плавающего типа с меньшей точностью в плавающий тип с
большей точностью значение не изменяется. Если, наоборот, переход осуществляется
от большей точности к меньшей и значение остаётся в допустимых пределах нового
типа, то результатом будет одно из двух ближайших значений нового типа. Если
результат выходит за границы диапазона допустимых значений, поведение программы
не определено.

\subsection{Арифметические преобразования}
\label{apx:subsec:arifmetic_conversion}

\index{преобразование!обычное арифметическое}%
Во многих операциях преобразование типов операндов и определение типа результата
осуществляются по одним и тем же правилам. Они состоят в том, что операнды
приводятся к некоторому общему типу, который также является и типом результата.
Эти правила называются \emph{обычными арифметическими преобразованиями}.

\begin{itemize}
 \item Если какой-либо из операндов имеет тип \verb|long double|, то другой
 приводится к \verb|long double|.
 \item В противном случае, если какой-либо из операндов имеет тип \verb|double|,
 то другой приводится к \verb|double|.
 \item В противном случае, если какой-либо из операндов имеет тип \verb|float|,
 то другой приводится к \verb|float|.
 \item В противном случае для обоих операндов осуществляется повышение
 целочисленности; затем, если один из операндов имеет тип
 \verb|unsigned long int|, то и другой преобразуется в \verb|unsigned long int|.
 \item В противном случае, если один из операндов принадлежит типу
 \verb|long int|, а другой -- \verb|unsigned int|, то результат зависит от того,
 покрывает ли \verb|long int| все значения \verb|unsigned int|, и если это так,
 то \verb|unsigned int| приводится к \verb|long int|, если нет, то оба операнда
 преобразуются в \verb|unsigned long int|.
 \item В противном случае, если один из операндов имеет тип \verb|long int|, то
 другой приводится к \verb|long int|.
 \item В противном случае, если один из операндов -- \verb|unsigned int|, то
 другой приводится к \verb|unsigned int|.
 \item В противном случае оба операнда имеют тип \verb|int|.
\end{itemize}

\begin{ApxComment}
Здесь два изменения. Во-первых, арифметика с \verb|float|-операндами теперь
может быть с одинарной точностью, а не только с двойной; в первой редакции вся
плавающая арифметика была с двойной точностью. Во-вторых, более короткий
беззнаковый тип в комбинации с более длинным знаковым типом не распространяет
свойство беззнаковости на тип результата; в первой редакции беззнаковый тип
всегда доминировал. Новые правила немного сложнее, но до некоторой степени
уменьшают вероятность появления неожиданных эффектов в комбинациях знаковых и
беззнаковых величин. При сравнении беззнакового выражения со знаковым того же
размера всё же может возникнуть неожиданный результат.
\end{ApxComment}

\subsection{Указатели и целые}
\label{apx:subsec:pointers_and_integers}

\index{вычитание из указателя}%
\index{преобразование!указателя}%
\index{преобразование!указатель -- целое|(}%
\index{преобразование!целое -- указатель}%
\index{указатели!арифметика с}%
\index{указатели!вычитание}%
\index{указатель!преобразование}%
К указателю можно прибавлять (и вычитать из него) выражение целочисленного типа;
последнее в этом случае подвергается преобразованию, описанному
в~\ref{apx:subsec:additive_operators} при рассмотрении оператора сложения.

К двум указателям на объекты одного типа, принадлежащие одному массиву, может
применяться операция вычитания; результат приводится к целому посредством
преобразования, описанного в~\ref{apx:subsec:additive_operators} при
рассмотрении оператора вычитания.

\index{указатель!пустой}%
\index{null-указатель}%
Целочисленное константное выражение со значением $0$ или оно же, но приведённое
к типу \verb|void *|, может быть преобразовано в указатель любого типа
операторами приведения, присваивания и сравнения. Результатом будет
\verb|null|-указатель, который равен любому другому \verb|null|-указателю того
же типа, но не равен никакому указателю, ссылающемуся на реальный объект или
функцию.

Допускаются и другие преобразования для указателей, но в связи с ними возникает
проблема зависимости результата от реализации. Эти преобразования должны быть
специфицированы явным оператором преобразования типа или оператором
приведения~(\ref{apx:subsec:conversion_operator}~и~\ref{apx:subsec:names_of_types}).

Указатель можно привести к достаточно большому для его хранения целочисленному
типу; требуемый размер зависит от реализации. Функция преобразования также
зависит от реализации.

Объект целочисленного типа можно явно преобразовать в указатель. Если целое
получено из указателя и имеет достаточно большой размер, это преобразование даст
тот же указатель; в противном случае результат зависит от реализации.
\index{переполнение|)}%


Указатель на один тип можно преобразовать в указатель на другой тип.
\index{выравнивание!ограничения по}%
Если исходный указатель ссылается на объект, должным образом не выровненный по
границам слов памяти, то в результате может получиться указатель, адресующий к
<<исключённому>> фрагменту. Если требования на выравнивание у нового типа меньше
или совпадают с требованиями на выравнивание первоначального типа, то
гарантируется, что преобразование указателя в другой тип и обратно его не
изменит; понятие <<выравнивание>> реализационно-зависимо, однако в любой
реализации объекты типа \verb|char| предъявляют минимальные требования на
выравнивание. Как описано в~\ref{apx:subsec:pointers_to_void}‚ указатель может
также преобразовываться в \verb|void *| и обратно, значение указателя при этом
не изменяется.

Указатель может быть преобразован в другой указатель того же типа с добавлением
или удалением
квалификаторов~(\ref{apx:subsec:type_qualifiers},~\ref{apx:subsec:type_specifiers})
того типа объекта, на который этот указатель ссылается. Новый указатель,
полученный добавлением квалификатора, имеет то же значение, но с дополнительными
ограничениями, внесёнными новыми квалификаторами. Операция по удалению
квалификатора у объекта приводит к тому, что восстанавливается действие его
начальных квалификаторов, заданных в декларации этого объекта.

Наконец, указатель на функцию может быть преобразован в указатель на функцию
другого типа. Вызов функции по преобразованному указателю зависит от реализации;
однако, если указатель ещё раз преобразовать к его исходному типу, результат
будет идентичен вызову по первоначальному указателю.
\index{преобразование!указатель -- целое|)}%


\subsection{Тип
\texorpdfstring{\protect\Verb|void|}{void}}

\index{void@\texttt{void}!тип}%
Значение (несуществующее) объекта типа \verb|void| никак нельзя использовать,
его также нельзя явно или неявно привести к типу отличному от \verb|void|.
Поскольку выражение типа \verb|void| обозначает отсутствие значения, его можно
применять только там, где не требуется значения; например, в качестве
выражения-инструкции~(\ref{apx:subsec:statement-expression}) или левого операнда
у оператора <<запятая>>~(\ref{apx:subsec:operator_comma}).

Выражение можно привести к типу \verb|void| операцией приведения типа. Например,
применительно к вызову функции, используемому в роли выражения-инструкции,
операция приведения к \verb|void| явным образом подчёркивает тот факт, что
результат функции отбрасывается.

\begin{ApxComment}
Тип \verb|void| не фигурировал в первом издании этой книги, однако за прошедшее
время стал общеупотребительным.
\end{ApxComment}

\subsection{Указатели на
\texorpdfstring{\protect\Verb|void|}{void}}
\label{apx:subsec:pointers_to_void}

\index{преобразование!указателя}%
\index{указатель!преобразование}%
\index{указатель!void *@\texttt{void *}}%
\index{void *, указатель@\texttt{void *}, указатель}%
Любой указатель на объект можно привести к типу \verb|void *| без потери
информации. Если результат подвергнуть обратному преобразованию, то мы получим
прежний указатель. В отличие от преобразований указатель-в-указатель
(рассмотренных в~\ref{apx:subsec:pointers_and_integers})‚ которые требуют явных
операторов приведения к типу, в присваиваниях и сравнениях указатель любого типа
может выступать в паре с указателем типа \verb|void *| без каких-либо
предварительных преобразований типа.

\begin{ApxComment}
Такая интерпретация указателей \verb|void *| -- новая; ранее роль обобщённого
указателя отводилась указателю типа \verb|char *|. Стандарт ANSI официально
разрешает использование указателей \verb|void *| совместно с указателями других
типов в присваиваниях и сравнениях; в иных комбинациях указателей стандарт
требует явных преобразований типа.
\end{ApxComment}
\index{тип!правила преобразования|)}%
\index{приведение к типу|)}%
\index{преобразование|)}%
\index{оператор!приведения к типу|)}%


\section{Выражения}

\index{выражение|(}%
\index{вычисление, порядок}%
\index{оператор!приоритет}%
\index{операторы!ассоциативные}%
\index{порядок!вычислений}%
\index{приоритеты операторов}%
Приоритеты описываемых операторов имеют тот же порядок, что и подразделы данного
параграфа (от высших к низшим). Например, для оператора \verb|+|, описанного
в~\ref{apx:subsec:additive_operators}, термин <<операнды>> означает <<выражения,
определённые
в~\ref{apx:subsec:generation_of_pointer}--\ref{apx:subsec:multiplication_operators}>>.
В каждом подразделе описываются операторы, имеющие одинаковый приоритет, и
указывается их ассоциативность (левая или правая). Приоритеты и ассоциативность
всех операторов отражены в грамматике, приведённой в~\ref{apx:sec:grammar}.

\index{выражение!порядок вычисления}%
\index{побочный эффект}%
\index{порядок!вычислений}%
Приоритеты и ассоциативность полностью определены, а вот порядок вычисления
выражения не определён за некоторым исключением даже для подвыражений с побочным
эффектом. Это значит, что если в определении оператора последовательность
вычисления его операндов специально не оговаривается, то в реализации можно
свободно выбирать любой порядок вычислений и даже перемежать правый и левый
порядок одновременно. Однако любой оператор использует значения своих операндов
в точном соответствии с грамматическим разбором выражения, в котором он
встречается.
%
% в оригинале в левом нижнем углу страницы надпись ``7. Заказ № 13''
%

\begin{ApxComment}
Это правило отменяет ранее предоставлявшуюся свободу в выборе порядка выполнения
операций, которые математически коммутативны и ассоциативны, но которые в
процессе вычислений могут таковыми не оказаться. Это изменение затрагивает
только вычисления с плавающей точкой, выполняющиеся <<на грани точности>>, и
ситуаций, когда возможно переполнение.
\end{ApxComment}

\index{исключительные ситуации}%
Контроль за переполнением, делением на нуль и другими исключительными
ситуациями, возникающими при вычислении выражения, в языке не определён. В
большинстве существующих реализаций Си при вычислении знаковых целочисленных
выражений и присваиваний переполнение игнорируется, но результат таких
вычислений не определён. Трактовки деления на нуль и всех исключительных
ситуаций, связанных с плавающей точкой, могут не совпадать в разных реализациях;
иногда для обработки исключительных ситуаций предоставляется нестандартная
библиотечная функция.

\subsection{Генерация указателя}
\label{apx:subsec:generation_of_pointer}

\index{массив!преобразование имени}%
\index{преобразование!имени массива}%
\index{указатель!генерация}%
Если для некоторого типа $T$ тип выражения или подвыражения есть <<массив из
$T$>>, то значением этого выражения является указатель на первый элемент
массива, и тип такого выражения заменяется на тип <<указатель на $T$>>. Такая
замена типа не делается, если выражение является операндом унарного оператора
\verb|&|, или операндом операций \verb|++|, \verb|--|, \verb|sizeof|, или левым
операндом присваивания, или операндом оператора <<\verb|.|>>.
\index{преобразование!функции}%
\index{функция!преобразование имени}%
Аналогично выражение типа <<функция, возвращающая $T$>>, исключая случай, когда
оно является операндом для \verb|&|, преобразуется в тип <<указатель на функцию,
возвращающую $T$>>.

\subsection{Первичные выражения}

\index{выражение!первичное}%
\index{первичное выражение}%
Первичные выражения -- это идентификаторы, константы, стринги и
\index{выражение!в скобках}%
выражения в скобках.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{первичное-выражение:}
     \textit{идентификатор}
     \textit{константа}
     \textit{стринг}
     ( \textit{выражение} )
\end{ShortGramDecsWithCC}

Идентификатор, если он был должным образом декларирован (о том, как это
делается, речь пойдёт ниже), -- первичное выражение. Тип идентификатора
специфицируется в его декларации. Идентификатор есть l-значение, если он
обозначает объект~(\ref{apx:sec:objects_and_lvalues}) арифметического типа либо
объект типа <<структура>>, <<объединение>> или <<указатель>>.

Константа -- первичное выражение. Её тип зависит от формы записи, которая была
рассмотрена в~\ref{apx:subsec:constants}.

Стринговый литерал -- первичное выражение.
\index{стринг!тип}%
\index{тип!стринга}%
Изначально его тип -- <<массив из \verb|char|>> (<<массив из \verb|wchar_t|>>
для стринга литер расширенного набора), но в соответствии с правилом‚
приведённым в~\ref{apx:subsec:generation_of_pointer}‚ указанный тип обычно
превращается в <<указатель на \verb|char|>> (<<указатель на \verb|wchar_t|>>) с
результирующим значением <<указатель на первую литеру стринга>>. Для некоторых
инициализаторов такая замена типа не
делается.~(См.~\ref{apx:subsec:initialization}.)

Выражение в скобках -- первичное выражение, тип и значение которого идентичны
типу и значению этого же выражения без скобок. Наличие или отсутствие скобок не
влияет на то, является ли данное выражение l-значением или нет.

\subsection{Постфиксные выражения}

\index{операторы!постфиксные \texttt{++} и \texttt{\textminus\textminus}}%
В постфиксных выражениях операторы выполняются слева направо.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{постфиксное-выражение:}
     \textit{первичное-выражение}
     \textit{постфиксное-выражение} [ \textit{выражение} ]
     \textit{постфиксное-выражение}\
( \textit{список-аргументов-выражений\textsubscript{необ}} )
     \textit{постфиксное-выражение} . \textit{идентификатор}
     \textit{постфиксное-выражение} -> \textit{идентификатор}
     \textit{постфиксное-выражение} ++
     \textit{постфиксное-выражение} --

\textit{список-аргументов-выражений:}
     \textit{выражение-присваивание}
     \textit{список-аргументов-выражений} , \textit{выражение-присваивание}
\end{ShortGramDecsWithCC}

\subsubsection{Ссылки на элементы массива}

\index{массив!ссылки на элементы}%
\index{массив!индексирование}%
\index{индексирование массива}%
Постфиксное выражение, за которым следует выражение в квадратных скобках, есть
постфиксное выражение, обозначающее ссылку в индексируемый массив. Одно из этих
двух выражений должно иметь тип <<указатель на $T$>>, где $T$ -- некоторый тип,
а другое -- принадлежать целочисленному типу; тип результата индексирования есть
$T$. Выражение \verb|E1[E2]| по определению идентично выражению
\verb|*((E1)+(E2))|. Подробности
см.~в~\ref{apx:subsubsec:declarators_of_arrays}.

\subsubsection{Вызов функции}
\label{apx:subsubsec:function_call}

\index{вызов}%
\index{именователь функции}%
\index{функция}%
\index{функция!вызов!семантика}%
\index{функция!вызов!синтаксис}%
\index{функция!именователь}%
Вызов функции есть постфиксное выражение (оно называется именователем функции),
за которым следуют скобки, содержащие (возможно, пустой) список разделённых
запятыми выражений-присваиваний~(\ref{apx:subsec:assignment_expression}),
представляющих собой аргументы этой функции.
\index{декларация!функции!неявная}%
\index{функция!неявная декларация}%
Если постфиксное выражение -- идентификатор, не описанный в текущей области
действия, то считается, что этот идентификатор как бы описан декларацией

\begin{ShortCodeParWithCC}{\\\{\}}
extern  int  \textit{идентификатор} ( );
\end{ShortCodeParWithCC}

\noindent помещённой в самом внутреннем блоке, содержащем вызов соответствующей
функции.
\index{по умолчанию!тип функции}%
\index{указатель!на функцию}%
\index{функция!тип по умолчанию}%
\index{функция!указатель на}%
Постфиксное выражение (после, возможно, неявного описания и генерации указателя,
см.~\ref{apx:subsec:generation_of_pointer}) должно иметь тип <<указатель на
функцию, возвращающую $T$>>, где $T$ -- тип возвращаемого значения.

\begin{ApxComment}
В первом издании для именователя функции допускался только тип <<функция>>, и,
чтобы вызвать функцию через указатель, требовался явный оператор \verb|*|.
ANSI-стандарт поощряет практику некоторых существующих компиляторов,
разрешающих иметь одинаковый синтаксис для обращения просто к функции и
обращения к функции, специфицированной указателем. Возможность применения
старого синтаксиса остаётся.
\end{ApxComment}
%
% в оригинале в левом нижнем углу страницы проставлено ``7*''
%

\index{определение!аргумента}%
\index{определение!параметра}%
\index{параметр}%
\index{параметр!определение}%
\index{прототип функции}%
\index{функция!аргумент}%
\index{функция!прототип}%
Термин \emph{аргумент} используется для выражения, задаваемого в вызове
функции; термин \emph{параметр} -- для обозначения в определении или описании
функции получаемого ею объекта (или его идентификатора). Вместо этих понятий 
иногда встречаются термины <<фактический аргумент (параметр)>> и <<формальный
аргумент (параметр)>>, имеющие те же смысловые различия.

При вызове функции копируется каждый её аргумент;
\index{вызов!по значению}%
передача аргументов осуществляется строго через их значения. Функции разрешается
изменять значения своих параметров, которые являются лишь копиями
аргументов-выражений, но эти изменения не могут повлиять на значения самих
аргументов.
\index{вызов!по ссылке}%
Однако можно передать указатель, чтобы дать возможность функции изменить
значение объекта, на который ссылается этот указатель.

\index{декларация!функции!новым способом}%
\index{прототип функции}%
\index{функция!прототип}%
\index{функция!в новом стиле}%
Имеются два способа декларирования функции. В новом способе типы параметров
задаются явно и являются частью типа функции; такая декларация называется
прототипом функции.
\index{декларация!функции!старым способом}%
\index{функция!в старом стиле}%
При старом способе типы параметров не указываются. Способы декларирования
функций обсуждаются
в~\ref{apx:subsubsec:declarators_of_functions}~и~\ref{apx:subsec:definitions_of_functions}.

\index{повышение!типа аргумента}%
\index{преобразование}%
Если вызов находится в области действия декларации, написанной по-старому,
каждый его аргумент подвергается операции повышения типа: для целочисленных
аргументов осуществляется повышение
целочисленности~(\ref{apx:subsec:integral_promotion}), а для
\verb|float|-аргументов -- преобразование в \verb|double|. Результат работы
вызова не определён, если число аргументов не соответствует количеству
параметров в определении функции или если типы аргументов после повышения не
согласуются с типами соответствующих параметров. Критерий согласованности типов
зависит от способа (старого или нового) определения функции. При старом способе
сравниваются повышенный тип аргумента в вызове и повышенный тип
соответствующего параметра; при новом способе повышенный тип аргумента и тип
параметра (без его повышения) должны быть одинаковыми.

\index{повышение!типа аргумента}%
\index{преобразование}%
Если вызов находится в области действия декларации, написанной по-новому,
аргументы преобразуются, как если бы они присваивались переменным, имеющим типы
соответствующих параметров прототипа.
\index{список!аргументов переменной длины}%
Число аргументов должно совпадать с числом явно описанных параметров, если
только список параметров не заканчивается многоточием (\verb|, ...|). В
противном случае число аргументов должно быть больше числа параметров или равно
ему; <<скрывающиеся>> под многоточием аргументы подвергаются операции повышения
типа (так, как это было описано в предыдущем абзаце). Если определение функции
задано по-старому, то типы параметров в прототипе, которые неявно присутствуют в
вызове, должны соответствовать типам параметров в определении функции после их
повышения.

\begin{ApxComment}
Эти правила особенно усложнились из-за того, что они призваны обслуживать
смешанный способ (старого с новым) задания функций. По возможности его следует
избегать.
\end{ApxComment}

\index{побочный эффект}%
Порядок вычисления аргументов не определяется, в разных компиляторах он
различен. Однако гарантируется, что аргументы и именователь функции вычисляются
полностью (включая и побочные эффекты) до входа в неё.
\index{рекурсия}%
Любая функция допускает рекурсивное обращение.

\subsubsection{Ссылки на члены структуры}

\index{оператор!доступа к члену структуры!точка@\texttt{.} (точка)}%
\index{структура!семантика ссылки на неё}%
\index{структура!синтаксис ссылки на неё}%
\index{структура!оператор доступа к её члену!\texttt{.} (точка)}%

Постфиксное выражение, за которым стоит точка с последующим идентификатором,
является постфиксным выражением. Выражение первого операнда должно быть
структурой или объединением, а идентификатор -- именем члена структуры или
объединения. Значение -- именованный член структуры или объединения, а тип
значения -- тип члена структуры или объединения. Выражение является l-значением,
если первое выражение -- l-значение и если тип второго выражения -- не
<<массив>>.

\index{оператор!доступа к члену структуры!через указатель \texttt{\textminus\textgreater}}%
\index{структура!оператор доступа к её члену!через указатель \texttt{\textminus\textgreater}}%
Постфиксное выражение, за которым указана стрелка (составленная из знаков
\verb|-| и \verb|>|) с последующим идентификатором, является постфиксным
выражением. Выражение первого операнда должно быть указателем на структуру
(объединение), а идентификатор -- именем члена структуры (объединения).
Результат -- именованный член структуры (объединения), на которую ссылается
указатель, а тип значения -- тип члена структуры (объединения); результат --
l-значение, если тип не есть <<массив>>.

Таким образом, выражение \verb|E1->MOS| означает то же самое, что и выражение
\verb|(*E1).MOS|. Структуры и объединения рассматриваются
в~\ref{apx:subsec:declaration_of_structures_and_unions}.

\begin{ApxComment}
В первом издании книги уже было приведено правило, по которому имя члена должно
принадлежать структуре или объединению, упомянутому в постфиксном выражении.
Там, однако, оговаривалось, что оно не является строго обязательным. Последние
компиляторы и ANSI делают его обязательным.
\end{ApxComment}

\subsubsection{Постфиксные инкрементирование и декрементирование}

\index{оператор!инкрементации \texttt{++}}%
\index{оператор!декрементации \texttt{\textminus\textminus}}%
\index{операторы!постфиксные \texttt{++} и \texttt{\textminus\textminus}}%
Постфиксное выражение, за которым следует \verb|++| или \verb|--|‚ есть
постфиксное выражение. Значением такого выражения является значение его
операнда. После того как значение было взято, операнд увеличивается (\verb|++|)
или уменьшается (\verb|--|) на $1$. Операнд должен быть l-значением; информация
об ограничениях, накладываемых на операнд, и деталях операций содержится
в~\ref{apx:subsec:additive_operators}‚ где обсуждаются аддитивные операторы, и
в~\ref{apx:subsec:assignment_expression}‚ где рассматривается присваивание.
Результат инкрементирования или декрементирования не есть l-значение.

\subsection{Унарные операторы}

\index{оператор!дополнения побитового до единиц \texttt{\textasciitilde}}%
\index{оператор!инкрементации \texttt{++}}%
\index{оператор!декрементации \texttt{\textminus\textminus}}%
\index{оператор!косвенности \texttt{*}}%
\index{оператор!унарного минуса \texttt{\textminus}}%
\index{оператор!унарного плюса \texttt{+}}%
\index{оператор!sizeof@\texttt{sizeof}}%
\index{операторы!префиксные \texttt{++} и \texttt{\textminus\textminus}}%
\index{преобразование|(}%
Выражения с унарными операторами выполняются справа налево.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{унарное-выражение:}
     \textit{постфиксное-выражение}
     ++ \textit{унарное-выражение}
     -- \textit{унарное-выражение}
     \textit{унарный-оператор}  \textit{выражение-приведённое-к-типу}
     sizeof  \textit{унарное-выражение}
     sizeof  ( \textit{имя-типа} )

\textit{унарный-оператор:} один из
     &    *    +    -    ~    !
\end{ShortGramDecsWithCC}

\subsubsection{Префиксные инкрементирование и декрементирование}

\index{оператор!инкрементации \texttt{++}}%
\index{оператор!декрементации \texttt{\textminus\textminus}}%
\index{операторы!постфиксные \texttt{++} и \texttt{\textminus\textminus}}%
\index{операторы!префиксные \texttt{++} и \texttt{\textminus\textminus}}%
Унарное выражение, перед которым стоит \verb|++| или \verb|--|, есть унарное
выражение. Операнд увеличивается (\verb|++|) или уменьшается (\verb|--|) на
$1$. Значением выражения является значение его операнда после увеличения
(уменьшения). Операнд всегда -- l-значение; информация об ограничениях на
операнд и деталях операции содержится в~\ref{apx:subsec:additive_operators}, где
обсуждаются аддитивные операторы, и в~\ref{apx:subsec:assignment_expression}‚
где рассматривается присваивание. Результат инкрементирования и
декрементирования не есть l-значение.

\subsubsection{Оператор получения адреса}

\index{переменная!адрес}%
Унарный оператор \verb|&| обозначает операцию получения адреса своего операнда.
Операнд должен быть либо l-значением, не ссылающимся ни на поле битов, ни на
объект, объявленный как \verb|register|, либо иметь тип <<функция>>. Результат
-- указатель на объект (или функцию), адресуемый этим l-значением. Если тип
операнда есть $T$, то типом результата является <<указатель на $T$>>.

\subsubsection{Оператор косвенности}

\index{оператор!косвенности \texttt{*}}%
Унарный оператор \verb|*| обозначает операцию косвенности (раскрытия указателя),
возвращающую объект (или функцию), на который указывает её операнд. Результат
есть l-значение, если операнд -- указатель на объект арифметического типа или на
объект типа <<структура>>, <<объединение>> или <<указатель>>. Если тип выражения
-- <<указатель на $T$>>, то тип результата -- $T$.

\subsubsection{Оператор унарный плюс}

\index{оператор!унарного плюса \texttt{+}}%
Операнд унарного \verb|+| должен иметь арифметический тип, результат -- значение
операнда. Целочисленный операнд подвергается повышению целочисленности. Типом
результата является повышенный тип операнда.

\begin{ApxComment}
Унарный \verb|+| был добавлен для симметрии с унарным \verb|-|.
\end{ApxComment}

\subsubsection{Оператор унарный минус}

\index{оператор!унарного минуса \texttt{\textminus}}%
Операнд для унарного \verb|-| должен иметь арифметический тип, результат --
значение операнда с противоположным знаком. Целочисленный операнд подвергается
повышению целочисленности. Отрицательное значение от беззнаковой величины
вычисляется вычитанием приведённого к повышенному типу операнда из максимального
числа повышенного типа, увеличенного на $1$; однако минус нуль есть нуль. Типом
результата будет повышенный тип операнда.

\subsubsection{Оператор обращения разрядов}

\index{оператор!дополнения побитового до единиц \texttt{\textasciitilde}}%
\index{операторы!побитовые}%
Операнд оператора \verb|~| должен иметь целочисленный тип, результат --
дополнение операнда до единиц по всем разрядам. Выполняется повышение
целочисленности типа операнда. Если операнд беззнаковый, то результат получается
вычитанием его значения из самого большого числа повышенного типа. Если операнд
знаковый, то результат вычисляется посредством приведения <<повышенного
операнда>> к беззнаковому типу, выполнения операции \verb|~| и обратного
приведения его к знаковому типу. Тип результата -- повышенный тип операнда.

\subsubsection{Оператор логического отрицания}

\index{оператор!логического отрицания \texttt{"!}}%
Операнд оператора \verb|!| должен иметь арифметический тип или быть указателем.
Результат равен $1$, если сравнение операнда с $0$ даёт истину, и равен $0$ в
противном случае. Тип результата -- \verb|int|.

\subsubsection{Оператор определения размера
\texorpdfstring{\protect\Verb|sizeof|}{sizeof}}
\label{apx:subsubsec:sizeof_operator}

\index{оператор!sizeof@\texttt{sizeof}}%
\index{структура!размер}%
Оператор \verb|sizeof| даёт число байтов, требуемое для хранения объекта того
типа, который имеет его операнд. Операнд -- либо выражение (которое не
вычисляется), либо имя типа, записанное в скобках. Применённый к \verb|char|
оператор \verb|sizeof| даёт $1$. Для массива результат равняется общему
количеству байтов в массиве, для структуры или объединения -- числу байтов в
объекте, включая и байты-заполнители, которые понадобились бы, если бы из
элементов составлялся массив. Размер массива из \verb|n| элементов всегда
равняется \verb|n|, помноженному на размер отдельного его элемента.
\index{незавершённый тип}%
\index{тип!незавершённый}%
Данный оператор нельзя применять к операнду типа <<функция>>, к незавершённому
типу и к полю битов.
\index{size{\_}t@\texttt{size{\_}t}}%
Результат -- беззнаковая целочисленная константа;
конкретный её тип зависит от реализации. В стандартном головном файле
\verb|<stddef.h>| (см. приложение~\ref{apx:stdlib}) этот тип определяется под
именем \verb|size_t|.

\subsection{Оператор приведения типа}
\label{apx:subsec:conversion_operator}

\index{оператор!приведения к типу}%
\index{преобразование!оператором приведения}%
\index{приведение к типу}%
Имя типа, записанное перед унарным выражением в скобках, вызывает приведение
значения этого выражения к указанному типу.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{выражение-приведённое-к-типу:}
     \textit{унарное-выражение}
     ( \textit{имя-типа} ) \textit{выражение-приведённое-к-типу}
\end{ShortGramDecsWithCC}

\noindent Данная конструкция называется \emph{приведением}. Имена типов даны
в~\ref{apx:subsec:names_of_types}. Результат преобразований описан
в~\ref{apx:sec:type_conversion}. Выражение с приведением типа не является
l-значением.

\subsection{Мультипликативные операторы}
\label{apx:subsec:multiplication_operators}

\index{оператор!деления \texttt{\slash}}%
\index{оператор!деления по модулю \texttt{\%}}%
\index{оператор!умножения \texttt{*}}%
\index{операторы!мультипликативные}%
Мультипликативные операторы \verb|*|, \verb|/| и \verb|%| выполняются слева
направо.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{мультипликативное-выражение:}
     \textit{выражение-приведённое-к-типу}
     \textit{мультипликативное-выражение} *\
\textit{выражение-приведённое-к-типу}
     \textit{мультипликативное-выражение} /\
\textit{выражение-приведённое-к-типу}
     \textit{мультипликативное-выражение} %\
\textit{выражение-приведённое-к-типу}
\end{ShortGramDecsWithCC}

Операнды операторов \verb|*| и \verb|/| должны быть арифметического типа,
оператора \verb|%| -- целочисленного типа. Над операндами осуществляются
обычные арифметические преобразования, которые приводят их значения к типу
результата.

Бинарный оператор \verb|*| обозначает умножение.

\index{обрезание!при делении}%
Бинарный оператор \verb|/| получает частное, а \verb|%| -- остаток от деления
первого операнда на второй; если второй операнд есть $0$, то результат не
определён. В противном случае всегда выполняется соотношение:
\verb|(a/b)*b + a%b| равняется \verb|a|. Если оба операнда не отрицательные, то
остаток не отрицательный и меньше делителя; в противном случае гарантируется
только, что абсолютное значение остатка меньше абсолютного значения делителя.

\subsection{Аддитивные операторы}
\label{apx:subsec:additive_operators}

\index{оператор!вычитания \texttt{\textminus}}%
\index{оператор!сложения \texttt{+}}%
\index{операторы!аддитивные}%
Аддитивные операторы \verb|+| и \verb|-| выполняются слева направо. Если
операнды имеют арифметический тип, то осуществляются обычные арифметические
преобразования. Для каждого оператора существует ещё несколько дополнительных
сочетаний типов.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{аддитивное-выражение:}
     \textit{мультипликативное-выражение}
     \textit{аддитивное-выражение} + \textit{мультипликативное-выражение}
     \textit{аддитивное-выражение} - \textit{мультипликативное-выражение}
\end{ShortGramDecsWithCC}

Результат выполнения оператора \verb|+| есть сумма его операндов.
\index{масштабирование целых в арифметике с указателями}%
\index{неправильная арифметика с указателями}%
\index{указатели!арифметика с}%
\index{указатели!коэффициент домножения целых в арифметике с}%
\index{указатели!неправильная арифметика с}%
Указатель на объект в массиве можно складывать с целочисленным значением. При
этом последнее преобразуется в адресное смещение посредством умножения его на
размер объекта, на который ссылается указатель. Сумма является указателем на
объект того же типа; только ссылается этот указатель на другой объект того же
массива, отстоящий от первоначального соответственно вычисленному смещению. Так,
если \verb|P| -- указатель на объект в массиве, то \verb|P+1| -- указатель на
его следующий объект. Если полученный в результате суммирования указатель
выводит за границы массива, то за исключением случая, когда он ссылается на
место, находящееся непосредственно за концом массива, результат будет
неопределённым.

\begin{ApxComment}
Возможность для указателя ссылаться на точку, расположенную сразу за концом
массива, является новой. Она узаконивает общепринятую практику организации
циклического перебора элементов массива.
\end{ApxComment}

Результат выполнения оператора \verb|-| есть разность операндов. Из указателя
можно вычитать значение любого целочисленного типа с теми же преобразованиями и
при тех же условиях, что и в сложении.

Если к двум указателям на объекты одного и того же типа применить оператор
вычитания, то в результате получится целочисленное значение со знаком,
представляющее собой расстояние между объектами, на которые ссылаются эти
указатели; указатель на следующий объект на $1$ больше указателя на предыдущий
объект.
\index{ptrdiff{\_}t@\texttt{ptrdiff{\_}t}}%
Тип результата зависит от реализации; в стандартном головном файле
\verb|<stddef.h>| он определён под именем \verb|ptrdiff_t|. Значение не
определено, если указатели ссылаются на объекты не одного и того же массива;
однако если \verb|P| указывает на последний элемент массива, то \verb|(P+1)-P|
имеет значение, равное $1$.

\subsection{Операторы сдвига}
\label{apx:subsec:shift_operators}

\index{оператор!левого сдвига \texttt{\textless}\texttt{\textless}}%
\index{оператор!правого сдвига \texttt{\textgreater}\texttt{\textgreater}}%
\index{операторы!побитовые}%
\index{операторы!сдвига}%
Операторы сдвига \verb|<<| и \verb|>>| выполняются слева направо. Для обоих
операторов каждый операнд должен иметь целочисленный тип, и каждый из них
подвергается повышению целочисленности. Тип результата совпадает с повышенным
типом левого операнда. Результат не определён, если правый операнд отрицателен
или его значение превышает число битов в типе левого выражения или равно ему.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{сдвиговое-выражение:}
     \textit{аддитивное-выражение}
     \textit{сдвиговое-выражение} >> \textit{аддитивное-выражение}
     \textit{сдвиговое-выражение} << \textit{аддитивное-выражение}
\end{ShortGramDecsWithCC}


\noindent Значение \verb|E1 << E2| равно значению \verb|E1| (рассматриваемому
как цепочка битов), сдвинутому влево на \verb|E2| бит; при отсутствии
переполнения такая операция эквивалентна умножению на $2^{\mathrm{E}2}$.
Значение \verb|E1 >> E2| равно значению \verb|E1|, сдвинутому вправо на
\verb|E2| битовые позиции. Если \verb|E1| беззнаковое или имеет неотрицательное
значение, то правый сдвиг эквивалентен делению на $2^{\mathrm{E}2}$‚ в противном
случае результат зависит от реализации.

\subsection{Операторы отношения}

\index{оператор!меньше или равно \texttt{\textless=}}%
\index{оператор!меньше \texttt{\textless}}%
\index{оператор!больше или равно \texttt{\textgreater=}}%
\index{оператор!больше \texttt{\textgreater}}%
\index{операторы!отношения}%
Операторы отношения выполняются слева направо, однако это свойство едва ли может
оказаться полезным; согласно грамматике языка выражение \verb|a<b<c| трактуется
так же, как \verb|(a<b)<c|‚ а результат вычисления \verb|a<b| всегда есть $0$
или $1$.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{выражение-отношения:}
     \textit{сдвиговое-выражение}
     \textit{выражение-отношения} < \textit{сдвиговое-выражение}
     \textit{выражение-отношения} > \textit{сдвиговое-выражение}
     \textit{выражение-отношения} <= \textit{сдвиговое-выражение}
     \textit{выражение-отношения} >= \textit{сдвиговое-выражение}
\end{ShortGramDecsWithCC}

\noindent Операторы: \verb|<| (меньше), \verb|>| (больше), \verb|<=| (меньше или
равно) и \verb|>=| (больше или равно) -- все выдают $0$, если специфицируемое
отношение ложно, и $1$, если оно истинно. Тип результата -- \verb|int|. Над
арифметическими операндами выполняются обычные арифметические преобразования.
\index{сравнение указателей}%
\index{указатели!сравнение}%
Можно сравнивать указатели на объекты одного и того же (без учёта
квалификаторов) типа; результат будет зависеть от их относительного расположения
в памяти. Допускается, однако, сравнение указателей на разные части одного и
того же объекта: если два указателя ссылаются на один и тот же простой объект,
то они равны; если они ссылаются на члены одной структуры, то указатель на член
с более поздней декларацией в структуре больше; если указатели ссылаются на
члены одного итого же объединения, то они равны; если указатели ссылаются на
элементы некоторого массива, то сравнение этих указателей эквивалентно сравнению
их индексов. Если \verb|P| указывает на последний элемент массива, то \verb|P+1|
больше, чем \verb|P|, хотя \verb|P+1| <<выводит>> нас за границы массива. В
остальных случаях результат сравнения не определён.

\begin{ApxComment}
Эти правила несколько ослабили ограничения, установленные в первой редакции
языка. Они позволяют сравнивать указатели на различные члены структуры и
объединения и легализуют сравнение с указателем, ссылающимся на место, которое
расположено непосредственно за концом массива.
\end{ApxComment}

\subsection{Операторы равенства}

\index{оператор!неравенства \texttt{"!=}}%
\index{оператор!равенства \texttt{==}}%
\index{операторы!равенства}%
\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{выражение-равенства:}
     \textit{выражение-отношения}
     \textit{выражение-равенства} == \textit{выражение-отношения}
     \textit{выражение-равенства} != \textit{выражение-отношения}
\end{ShortGramDecsWithCC}

\noindent Операторы \verb|==| (равно) и \verb|!=| (не равно) являются аналогами
операторов отношения с той лишь разницей, что они имеют более низкий приоритет.
(Таким образом, \verb|a<b == c<d| есть $1$ тогда и только тогда, когда отношения
\verb|a<b| и \verb|c<d| оба одновременно истинны или ложны.)

\index{сравнение указателей}%
\index{указатели!сравнение}%
Операторы равенства подчиняются тем же правилам, что и операторы отношения. И
кроме того, они дают возможность сравнивать указатель с целочисленным
константным выражением, значение которого равно нулю, и с указателем на
\verb|void|.~(См.~\ref{apx:subsec:pointers_and_integers}.)

\index{операторы!побитовые|(}%
\subsection{Оператор побитового И}

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{И-выражение:}
     \textit{выражение-равенства}
     \textit{И-выражение} & \textit{выражение-равенства}
\end{ShortGramDecsWithCC}

\noindent Выполняются обычные арифметические преобразования; результат --
побитовое И операндов. Оператор применяется только к целочисленным операндам.

\subsection{Оператор побитового исключающего ИЛИ}

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{исключающее-ИЛИ-выражение:}
     \textit{И-выражение}
     \textit{исключающее-ИЛИ-выражение} ^ \textit{И-выражение}
\end{ShortGramDecsWithCC}

\noindent Выполняются обычные арифметические преобразования; результат --
побитовое исключающее ИЛИ операндов. Оператор применяется только к целочисленным
операндам.

\subsection{Оператор побитового ИЛИ}

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{ИЛИ-выражение:}
     \textit{исключающее-ИЛИ-выражение}
     \textit{ИЛИ-выражение} | \textit{исключающее-ИЛИ-выражение}
\end{ShortGramDecsWithCC}

\noindent Выполняются обычные арифметические преобразования; результат --
побитовое ИЛИ операндов. Оператор применяется только к целочисленным операндам.
\index{операторы!побитовые|)}%


\subsection{Оператор логического И}

\index{оператор!логического И \texttt{\&\&}}%
\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{логическое-И-выражение:}
     \textit{ИЛИ-выражение}
     \textit{логическое-И-выражение} && \textit{ИЛИ-выражение}
\end{ShortGramDecsWithCC}

\noindent Операторы \verb|&&| выполняются слева направо. Оператор \verb|&&|
выдаёт $1$, если оба операнда не равны нулю, и $0$ в противном случае. В отличие
от \verb|&|, \verb|&&| гарантирует, что вычисления будут проводиться слева
направо: вычисляется первый операнд со всеми побочными эффектами; если он равен
$0$, то значение выражения есть $0$. В противном случае вычисляется правый
операнд, и, если он равен $0$, то значение выражения есть $0$, в противном
случае оно равно $1$.

Операнды могут принадлежать разным типам, но либо операнд должен иметь
арифметический тип, либо быть указателем. Тип результата -- \verb|int|.

\subsection{Оператор логического ИЛИ}

\index{оператор!логического ИЛИ \texttt{"|"|}}%
\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{логическое-ИЛИ-выражение:}
     \textit{логическое-И-выражение}
     \textit{логическое-ИЛИ-выражение} || \textit{логическое-И-выражение}
\end{ShortGramDecsWithCC}

\noindent Операторы \verb+||+ выполняются слева направо. Оператор \verb+||+
выдаёт $1$, если по крайней мере один из операндов не равен нулю, и $0$ в
противном случае. В отличие от \verb+|+, оператор \verb+||+ гарантирует, что
вычисления будут проводиться слева направо: вычисляется первый операнд, включая
все побочные эффекты; если он не равен $0$, то значение выражения есть $1$. В
противном случае вычисляется правый операнд, и, если он не равен $0$, то
значение выражения есть $1$, в противном случае оно равно $0$.

Операнды могут принадлежать разным типам, но либо операнд должен иметь
арифметический тип, либо быть указателем. Тип результата -- \verb|int|.

\subsection{Условный оператор}

\index{условное выражение}%
\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{условное-выражение:}
     \textit{логическое-ИЛИ-выражение}
     \textit{логическое-ИЛИ-выражение} ?\
\textit{выражение} : \textit{условное-выражение}
\end{ShortGramDecsWithCC}

\noindent Вычисляется первое выражение, включая все побочные эффекты; если оно
не равно $0$, то результат есть значение второго выражения, в противном случае
-- значение третьего выражения. Вычисляется только один из двух последних
операндов: второй или третий. Если второй и третий операнды арифметические, то
выполняются обычные арифметические преобразования, приводящие к некоторому
общему типу, который и будет типом результата. Если оба операнда имеют тип
\verb|void|, или являются структурами или объединениями одного и того же типа,
или представляют собой указатели на объекты одного и того же типа, то результат
будет иметь тот же тип, что и операнды. Если один из операндов имеет тип
<<указатель>>, а другой является константой $0$, то $0$ приводится к типу
<<указатель>>, этот же тип будет иметь и результат. Если один операнд является
указателем на \verb|void|, а второй -- указатель другого типа, то последний
преобразуется в указатель на \verb|void|, который и будет типом результата.
%
% исправлена опечатка
% в оригинале "операды"
%

\index{квалификатор типа}%
\index{тип!квалификатор}%
При сравнении типов указателей квалификаторы
типов~(\ref{apx:subsec:type_specifiers}) объектов, на которые указатели
ссылаются, во внимание не принимаются, но тип результата наследует квалификаторы
обеих ветвей условного выражения.

\subsection{Выражения присваивания}
\label{apx:subsec:assignment_expression}

\index{выражение!присваивание}%
\index{операторы!присваивания}%
\index{оператор!присваивания \texttt{=}}%
\index{оператор!присваивания \texttt{*=}}%
\index{оператор!присваивания \texttt{\slash=}}%
\index{оператор!присваивания \texttt{\%=}}%
\index{оператор!присваивания \texttt{+=}}%
\index{оператор!присваивания \texttt{\textminus=}}%
\index{оператор!присваивания \texttt{\textless}\texttt{\textless=}}%
\index{оператор!присваивания \texttt{\textgreater}\texttt{\textgreater=}}%
\index{оператор!присваивания \texttt{\&=}}%
\index{оператор!присваивания \texttt{\textasciicircum=}}%
\index{оператор!присваивания \texttt{"|=}}%
\index{преобразование!присваиванием}%
\index{присваивание!выражение}%
Существует несколько операторов присваивания; они выполняются справа налево.

{\setlength{\codeIndent}{\codeIndentBk-0.25em}
\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{выражение-присваивания:}
     \textit{условное-выражение}
     \textit{унарное-выражение} \textit{оператор-присваивания}\
\textit{выражение-присваивания}

\textit{оператор-присваивания:} один из
     =    *=    /=    %=    +=    -=    <<=    >>=    &=    ^=    |=
\end{ShortGramDecsWithCC}
\setlength{\codeIndent}{\codeIndentBk}}

\noindent Операторы присваивания в качестве левого операнда требуют l-значения,
причём модифицируемого; это значит, что оно не может быть массивом, или иметь
незавершённый тип, или быть функцией. Тип левого операнда, кроме того, не может
иметь
\index{квалификатор типа}%
квалификатор \verb|const|; и, если он является структурой или объединением, в
них не должно быть членов или подчленов (для вложенных структур или объединений)
с квалификаторами \verb|const|. Тип выражения присваивания -- тип его левого
операнда, а значение -- значение его левого операнда после завершения
присваивания.

\index{преобразование!присваиванием}%
В простом присваивании с оператором \verb|=| значение выражения замещает объект,
на который ссылается l-значение. При этом должно выполняться одно из следующих
условий: оба операнда имеют арифметический тип (если типы операндов разные,
правый операнд приводится к типу левого операнда); оба операнда есть структуры
или объединения одного и того же типа; один операнд есть указатель, а другой --
указатель на \verb|void|; левый операнд -- указатель, а правый -- константное
выражение со значением $0$; оба операнда -- указатели на функции или объекты,
имеющие одинаковый тип (за исключением возможного отсутствия \verb|const| или
\verb|volatile| у правого операнда).

Выражение \verb|E1 |\textit{\Verb|op|}\verb| = E2| эквивалентно выражению
\verb|E1 = E1 |\textit{\Verb|op|}\verb| (E2)| с одним исключением: \verb|E1|
вычисляется только один раз.

\subsection{Оператор запятая}
\label{apx:subsec:operator_comma}

\index{оператор!запятая \texttt{,}}%
\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{выражение:}
     \textit{выражение-присваивания}
     \textit{выражение} , \textit{выражение-присваивания}
\end{ShortGramDecsWithCC}

\noindent Два выражения, разделённые запятой, вычисляются слева направо, и
значение левого выражения отбрасывается. Тип и значение результата совпадают с
типом и значением правого операнда. Вычисление всех побочных эффектов левого
операнда завершается перед началом вычисления правого операнда. В контексте, в
котором запятая имеет специальное значение, например в списках аргументов
функций~(\ref{apx:subsubsec:function_call}) или в списках
инициализаторов~(\ref{apx:subsec:initialization}) (здесь в качестве
синтаксических единиц фигурируют выражения присваивания), оператор запятая может
появиться только в группирующих скобках. Например, в

\begin{ShortCodePar}
f(a, (t=3, t+2), c)
\end{ShortCodePar}

\noindent три аргумента, из которых второй имеет значение $5$.

\subsection{Константные выражения}
\label{apx:subsec:constant_expressions}

\index{выражение!константное}%
\index{константное выражение}%
Синтаксически, константное выражение -- это выражение с ограниченным
подмножеством операторов:

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{константное-выражение:}
     \textit{условное-выражение}
\end{ShortGramDecsWithCC}

\noindent При указании \verb|case|-меток в переключателе, задании границ
массивов и длин полей битов, на месте значений перечислимых констант и
инициализаторов, а также в некоторых выражениях для препроцессора требуются
выражения, вычисление которых приводит к константе.

Константные выражения не могут содержать присваиваний, операторов
инкрементирования и декрементирования, вызовов функций и операторов-запятых;
перечисленные ограничения не распространяются на операнд \verb|sizeof|. Если
требуется получить целочисленное константное выражение, то его операнды должны
состоять из целых, перечислимых, литерных и плавающих констант; операции
приведения должны специфицировать целочисленный тип, а любая плавающая константа
-- приводиться к целому. Из этого следует, что в константном выражении не может
быть массивов, операций раскрытия указателя, получения адреса и доступа к полям
структуры. (Однако для \verb|sizeof| возможны операнды любого вида.)

Для константных выражений в инициализаторах допускается б\'{o}льшая свобода;
операндами могут быть константы любого типа, а к внешним или статическим
объектам и внешним и статическим массивам, индексируемым константными
выражениями, возможно применять унарный оператор \verb|&|. Унарный оператор
\verb|&| может также неявно <<присутствовать>> при использовании массива без
индекса или функции без списка аргументов. Вычисление инициализатора должно
давать константу или адрес ранее декларированного внешнего или статического
объекта плюс-минус константа.

Меньшая свобода допускается для целочисленных константных выражений,
используемых после \verb|#if|: не разрешаются \verb|sizeof|-выражения‚
перечислимые константы и операции приведения
типа.~(См.~\ref{apx:subsec:conditional_compilation}.)
\index{преобразование|)}%
\index{выражение|)}%


\section{Декларации}

\index{декларация|(}%
То, каким образом интерпретируется каждый идентификатор, специфицируется
декларациями; они не всегда резервируют память для описываемых ими
идентификаторов.
\index{декларация!а не определение}%
\index{память!резервирование}%
\index{резервирование памяти}%
Декларации, резервирующие память, называются \emph{определениями} и имеют
следующий вид:

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{декларация:}
     \textit{спецификаторы-декларации}\
\textit{список-иниц-деклараторов\textsubscript{необ}};
\end{ShortGramDecsWithCC}

\noindent Деклараторы в \textit{список-иниц-деклараторов} содержат декларируемые
идентификаторы; \textit{спецификаторы-декларации} представляют собой
последовательности, состоящие из спецификаторов типа и класса памяти.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{спецификаторы-декларации:}
     \textit{спецификатор-класса-памяти}\
\textit{спецификаторы-декларации\textsubscript{необ}}
     \textit{спецификатор-типа}\
\textit{спецификаторы-декларации\textsubscript{необ}}
     \textit{квалификатор-типа}\
\textit{спецификаторы-декларации\textsubscript{необ}}

\textit{список-иниц-деклараторов:}
     \textit{иниц-декларатор}
     \textit{список-иниц-деклараторов} , \textit{иниц-декларатор}
\textit{иниц-декларатор:}
     \textit{декларатор}
     \textit{декларатор} = \textit{инициализатор}
\end{ShortGramDecsWithCC}

\noindent Деклараторы содержат подлежащие описанию имена. Мы рассмотрим их
позже, в~\ref{apx:subsec:declarators}. Либо декларация должна иметь по крайней
мере один декларатор, либо её спецификатор типа должен определять тег структуры
или объединения, либо -- задавать члены перечисления; пустая декларация
незаконна.

\subsection{Спецификаторы класса памяти}

\index{декларация!класса памяти}%
\index{декларация!typedef@\texttt{typedef}}%
\index{определение!класса памяти}%
\index{память!декларация класса}%
\index{память!определение}%
\index{память!спецификатор класса}%
\index{спецификатор!класса памяти}%
\index{спецификатор!auto@\texttt{auto}}%
\index{спецификатор!extern@\texttt{extern}}%
\index{спецификатор!register@\texttt{register}}%
\index{спецификатор!static@\texttt{static}}%
\index{auto@\texttt{auto}}%
\index{extern@\texttt{extern}}%
\index{register@\texttt{register}}%
\index{static@\texttt{static}!спецификатор класса памяти}%
\index{typedef-декларация@\texttt{typedef}-декларация}%
Класс памяти специфицируется следующим образом:

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{спецификатор-класса-памяти:}
     auto
     register
     static
     extern
     typedef
\end{ShortGramDecsWithCC}

\noindent Смысл классов памяти обсуждался
в~\ref{apx:sec:what_identificators_mean}.

Спецификаторы \verb|auto| и \verb|register| дают декларируемым объектам класс
автоматической памяти, и эти спецификаторы можно применять только внутри
функций. Декларации с \verb|auto| и \verb|register| одновременно являются
определениями и резервируют память. Спецификатор \verb|register| эквивалентен
\verb|auto|, но содержит подсказку, сообщающую, что в программе декларируемые им
объекты используются интенсивно. На регистрах может быть размещено лишь
небольшое число объектов, причём определённого типа; указанные ограничения
зависят от реализации.
\index{регистр, адрес}%
В любом случае к \verb|register|-объекту нельзя применять
(явно или неявно) унарный оператор \verb|&|.

\begin{ApxComment}
Новым является правило, согласно которому вычислять адрес объекта класса
\verb|register| нельзя, а класса \verb|auto| можно.
\end{ApxComment}

\index{static-переменные@\texttt{static}-переменные!внутренние}%
Спецификатор \verb|static| даёт декларируемым объектам класс статической памяти,
он может использоваться и внутри, и вне функций. Внутри функции этот
спецификатор вызывает выделение памяти и служит определением; его роль вне
функций будет объяснена в~\ref{apx:subsec:links}.

Декларация со спецификатором \verb|extern|, используемая внутри функции,
объявляет, что для декларируемого объекта где-то выделена память; о её роли вне
функций будет сказано в~\ref{apx:subsec:links}.
%
% исправлена опечатка
% в оригинале было "external"
%

Спецификатор \verb|typedef| не резервирует никакой памяти и назван
спецификатором класса памяти из соображений стандартности синтаксиса; речь об
этом спецификаторе пойдёт в~\ref{apx:subsec:typedef_declaration}.

Декларация может содержать не более одного спецификатора класса памяти.
\index{опущенный спецификатор!класса памяти}%
\index{память!спецификатор класса!опущенный}%
\index{спецификатор!класса памяти!опущенный}%
Если он в декларации отсутствует, то действуют следующие правила: считается, что
объекты, декларируемые внутри функций, имеют класс \verb|auto|; функции,
декларируемые внутри функций, -- класс \verb|extern|;
\index{связь!внешняя}%
объекты и функции, декларируемые вне функций, -- статические и имеют внешние
связи~(\ref{apx:sec:external_declarations},~\ref{apx:sec:scope}).

\subsection{Спецификаторы типа}
\label{apx:subsec:type_specifiers}

\index{спецификатор!типа}%
\index{тип!спецификатор}%
\index{char@\texttt{char}!тип}%
\index{double@\texttt{double}!тип}%
\index{float@\texttt{float}!тип}%
\index{int@\texttt{int}!тип}%
\index{long@\texttt{long}!тип}%
\index{short@\texttt{short}}%
\index{signed@\texttt{signed}!тип}%
\index{unsigned@\texttt{unsigned}!тип}%
\index{void@\texttt{void}!тип}%
Спецификаторы типа определяются следующим образом:

\begin{LongGramDecsWithCC}{\\\{\}}
\textit{спецификатор-типа:}
     void
     char
     short
     int
     long
     float
     double
     signed
     unsigned
     \textit{структ-или-объед-спецификатор}
     \textit{enum-спецификатор}
     \textit{typedef-имя}
\end{LongGramDecsWithCC}

\noindent Вместе с \verb|int| допускается использование ещё какого-то одного
слова -- \verb|long| или \verb|short|; причём сочетание \verb|long int| имеет
тот же смысл, что и просто \verb|long|; аналогично \verb|short int| -- то же
самое, что и \verb|short|. Слово \verb|long| может употребляться вместе с
\verb|double|. С \verb|int| и другими его модификациями (\verb|short|,
\verb|long| или \verb|char|) разрешается употреблять одно из слов \verb|signed|
или \verb|unsigned|. 
\index{опущенный спецификатор!типа}%
\index{тип!опущенный спецификатор}%
Любое из последних может использоваться самостоятельно, в этом случае
подразумевается \verb|int|. Спецификатор \verb|signed| бывает полезен, когда
требуется обеспечить, чтобы \verb|char|-объекты имели знак; его можно применять
и к другим целочисленным типам, но в этих случаях он избыточен.

За исключением описанных выше случаев декларация не может содержать более одного
спецификатора типа. Если в декларации нет ни одного спецификатора типа, то
имеется в виду тип \verb|int|.

\index{квалификатор типа}%
\index{тип!квалификатор}%
\index{const@\texttt{const}}%
\index{volatile@\texttt{volatile}}%
Для указания особых свойств декларируемых объектов предназначаются
квалификаторы:

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{квалификатор-типа:}
     const
     volatile
\end{ShortGramDecsWithCC}

\noindent Квалификаторы типа могут употребляться с любым спецификатором типа.
\verb|const|-объект разрешается инициализировать, однако присваивать ему
что-либо в дальнейшем запрещается. Смысл квалификатора \verb|volatile| зависит
от реализации.

\begin{ApxComment}
Средства \verb|const| и \verb|volatile| (изменчивый) введены ANSI-стандартом.
Квалификатор \verb|const| применяется, чтобы разместить объекты в памяти,
открытой только на чтение, или чтобы способствовать возможной оптимизации.
Назначение квалификатора \verb|volatile| -- подавить оптимизацию, которая без
этого указания могла бы возникнуть. Например, в машинах, где адреса регистров
ввода-вывода отображены на адресное пространство памяти, указатель на регистр
некоторого устройства мог бы быть декларирован как \verb|volatile|‚ чтобы
запретить компилятору экономить очевидно избыточную ссылку через указатель.
Компилятор может игнорировать указанные квалификаторы, однако обязан
сигнализировать о явных попытках изменить значение \verb|const|-объектов.
\end{ApxComment}

\subsection{Декларации структур и объединений}
\label{apx:subsec:declaration_of_structures_and_unions}

\index{объединение, тег|(}%
\index{спецификатор!struct@\texttt{struct}}%
\index{спецификатор!union@\texttt{union}}%
\index{структура!вложенная}%
\index{структура!тег|(}%
\index{тег!объединения|(}%
\index{тег!структуры|(}%
\index{union@\texttt{union}!спецификатор}%
Структура -- это объект, состоящий из последовательности именованных членов
различных типов. Объединение -- объект, который в каждый момент времени содержит
один из нескольких членов различных типов.
\index{декларация!структуры}%
\index{структура!декларация}%
\index{декларация!union@\texttt{union}}%
\index{struct, спецификатор@\texttt{struct}, спецификатор}%
\index{union@\texttt{union}!декларация}%
Декларации структур и объединений имеют один и тот же вид.

{\setlength{\codeIndent}{\codeIndentBk-0.75em}%
\begin{ShortGramDecsWithCC}{\\\[\]}
\textit[структ-или-объед-спецификатор:]
     \textit[структ-или-объед] \textit[идентификатор\textsubscript[необ]]\
{ \textit[список-структ-деклараций] }
     \textit[структ-или-объед] \textit[идентификатор]

\textit[структ-или-объед:]
     struct
     union
\end{ShortGramDecsWithCC}
\setlength{\codeIndent}{\codeIndentBk}}

\noindent \emph{Список-структ-деклараций} является последовательностью деклараций членов структуры или объединения:

{\setlength{\codeIndent}{\codeIndentBk-0.75em}%
\begin{LongGramDecsWithCC}{\\\{\}}
\textit{список-структ-деклараций:}
     \textit{структ-декларация}
     \textit{список-структ-деклараций}\
\textit{структ-декларация}

\textit{структ-декларация:}
     \textit{список-спецификаторов-квалификаторов}\
\textit{список-структ-деклараторов};

\textit{список-спецификаторов-квалификаторов:}
     \textit{спецификатор-типа}\
\textit{список-спецификаторов-квалификаторов\textsubscript{необ}}
     \textit{квалификатор-типа}\
\textit{список-спецификаторов-квалификаторов\textsubscript{необ}}

\textit{список-структ-деклараторов:}
     \textit{структ-декларатор}
     \textit{список-структ-деклараторов} , \textit{структ-декларатор}
\end{LongGramDecsWithCC}
\setlength{\codeIndent}{\codeIndentBk}}

\noindent Обычно \textit{структ-декларатор} -- это просто декларатор члена
структуры или объединения. Членом структуры может быть также некоторая
последовательность битов заданной длины. Такой член называется
\index{битовое поле}%
\index{битовое поле!декларация}%
\index{декларация!поля битов}%
\emph{полем-бит} или просто \emph{полем}; указатель его длины отделяется от
декларатора имени поля двоеточием.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{структ-декларатор:}
     \textit{декларатор}
     \textit{декларатор\textsubscript{необ}} : \textit{константное-выражение}
\end{ShortGramDecsWithCC}

Спецификатор типа, имеющий вид

\begin{ShortGramDecsWithCC}{\\\[\]}
\textit[структ-или-объед] \textit[идентификатор]\
{ \textit[список-структ-деклараций] }
\end{ShortGramDecsWithCC}

\noindent декларирует \textit{идентификатор} как \emph{тег} структуры
(объединения), задаваемый списком. Последующие декларации в той же или более
внутренней области действия могут ссылаться в спецификаторе на этот тип при
помощи тега (без списка):

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{структ-или-объед} \textit{идентификатор}
\end{ShortGramDecsWithCC}

\noindent%
\index{незавершённый тип}%
\index{тип!незавершённый}%
Если спецификатор с тегом без списка обнаружен в тот момент, когда тег
ещё не декларирован, то считается, что специфицирован \emph{незавершённый тип}.
На объект с незавершённым типом структуры (объединения) можно ссылаться в
контексте, где не нужен его размер, например, в декларациях (но не в
определениях), в спецификации указателя или при задании \verb|typedef|, но ни в
каких других случаях. Тип становится завершённым при появлении спецификатора с
тегом структуры или объединения, содержащего список деклараций. Но и в
спецификаторах со списком определяемые ими типы внутри списка остаются
незавершёнными до тех пор, пока не встретится завершающая спецификатор фигурная
скобка.

В структуру не могут входить члены с незавершённым типом. Следовательно‚ нельзя
декларировать структуру (объединение), содержащую саму себя.
\index{структура!ссылающаяся на себя}%
\index{структуры взаимно рекурсивные}%
Однако, помимо того что теги являются именами типов структур или объединений,
они позволяют определять структуры (объединения), ссылающиеся сами на себя;
структура (объединение) может содержать указатель на объект этой же структуры
(объединения), поскольку указатели с незавершёнными типами декларировать
разрешено.

В отношении деклараций вида

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{структ-или-объед} \textit{идентификатор} ;
\end{ShortGramDecsWithCC}

\noindent которые объявляют структуру или объединение, однако не имеют ни
списка, ни деклараторов, действует специальное правило. Даже если этот
идентификатор уже был декларирован во внешней области
действия~(\ref{apx:subsec:lexical_scope}) в качестве тега структуры или
объединения, в текущей области действия указанная декларация делает его тегом
нового незавершённого типа для структуры или объединения.

\begin{ApxComment}
Это <<неясное>> правило введено ANSI-стандартом. Оно позволяет во внутренней
области действия программы создавать <<взаимно-рекурсивные>> декларации структур
с тегами, которые уже могли быть объявлены во внешней области действия.
\end{ApxComment}

Спецификатор структуры или объединения со списком, но без тега, представляет
собой уникальный тип; на него можно сослаться только в той декларации, частью
которой он является.

\index{структура!имя члена}%
\index{член структуры, имя}%
Имена членов и тегов не <<конфликтуют>> ни между собой, ни с именами обычных
переменных. Имя члена нельзя употребить дважды в одной и той же структуре или
объединении, но одно и то же имя можно использовать в различных структурах и
объединениях.

\begin{ApxComment}
В первом издании этой книги имена членов не были локализованы в своей структуре
или объединении. Однако такая локализация стала общеупотребительной ещё до
принятия ANSI-стандарта для Си.
\end{ApxComment}
\index{тег!структуры|)}%
\index{тег!объединения|)}%
\index{структура!тег|)}%
\index{объединение, тег|)}%



Член (не поле) может быть объектом любого типа.
\index{битовое поле!выравнивание}%
Поле (которое может и не иметь декларатора и, следовательно, быть без имени)
имеет тип \verb|int|, \verb|unsigned int| или \verb|signed int| и
интерпретируется как объект целочисленного типа с заданным числом битов;
рассматривается ли поле типа \verb|int| как знаковое, зависит от реализации.
Также от реализации зависит способ и порядок <<упаковки>> соседних полей в
памяти. Если поле, следующее за другим полем, не помещается в частично
заполненной ячейке памяти, то либо оно будет разрезано на части, которые попадут
в разные ячейки, либо в структуре возникнут пропуски из неиспользуемых разрядов.
Поле без имени длины $0$ предписывает пропустить оставшиеся разряды и следующее
поле расположить с начала ячейки памяти.

\begin{ApxComment}
В сравнении с первым изданием ANSI-стандарт устанавливает ещё большую
зависимость полей от реализации. Разумно правила языка, касающиеся размещения
полей битов, рассматривать без каких-либо оговорок как
<<реализационно-зависимые>>. Структуры с полями битов полезны и как
универсальный способ минимизации памяти, требуемой под структуры, возможно, за
счёт увеличения количества команд и замедления доступа к полям, и как способ
описания побитового расположения информации. Во втором случае необходимо знать
особенности конкретной реализации.
\end{ApxComment}

Члены структуры имеют адреса, возрастающие в порядке написания их деклараций.
Член структуры (не поле) выравнивается по адресуемым границам слов в
соответствии со своим типом; следовательно, в структуре могут возникать
безымянные <<дыры>>. Если указатель на структуру привести к типу указателя на её
первый член, то в результате получится указатель на первый член структуры.

Объединение можно считать как бы структурой, все члены которой имеют смещение
$0$ от её начала, и которая обладает достаточным размером, чтобы вмещать любой
из своих членов. В каждый отдельный момент объединение может хранить значение
только одного своего члена. Если указатель на объединение привести к типу
какого-то из его членов, то в результате получится указатель на этот член.

Вот простой пример декларации структуры, которая содержит массив из 20 литер,
целое и две ссылки на такие же структуры.

\begin{ShortCodePar}
struct tnode {
    char tword[20];
    int count;
    struct tnode *left;
    struct tnode *right;
};
\end{ShortCodePar}

\noindent Если после указанной декларации поместить запись

\begin{ShortCodePar}
struct tnode s, *sp;
\end{ShortCodePar}

\noindent то она будет определять \verb|s| как структуру заданного вида, а
\verb|sp| -- как указатель на такую структуру. Согласно приведённым определениям
выражение

\begin{ShortCodePar}
sp->count
\end{ShortCodePar}

\noindent есть ссылка на член \verb|count| в структуре, на которую указывает
\verb|sp|;

\begin{ShortCodePar}
s.left
\end{ShortCodePar}

\noindent -- указатель на левое поддерево в структуре \verb|s|; а

\begin{ShortCodePar}
s.right->tword[0]
\end{ShortCodePar}

\noindent есть первая литера из \verb|tword| -- члена правого поддерева
\verb|s|.

Вообще говоря, нет способа проконтролировать, используется тот ли член
объединения, которому последний раз присваивалось значение. Однако гарантируется
выполнение правила, облегчающего работу с членами объединения: если объединение
содержит несколько структур, начинающихся с общей для них последовательности
данных, и если объединение в текущий момент содержит одну из этих структур, то
на общую часть данных разрешается ссылаться через любую из указанных структур.
Так, правомерен следующий фрагмент программы:

\begin{LongCodePar}
union {
    struct {
        int type;
    } n;
    struct {
        int type;
        int intnode;
    } ni;
    struct {
        int type;
        float floatnode;
    } nf;
} u;
...
u.nf.type = FLOAT;
u.nf.floatnode = 3.14;
...
if (u.n.type == FLOAT)
    ... sin(u.nf.floatnode) ...
\end{LongCodePar}

\subsection{Перечисления}
\label{apx:subsec:enumerations}

\index{константа!перечисления|(}%
\index{перечисление!константа|(}%
\index{перечисление!тег|(}%
\index{перечислитель}%
\index{спецификатор!enum@\texttt{enum}}%
\index{тег!перечисления|(}%
Перечисления -- это уникальный тип, значения которого покрываются множеством
именованных констант, называемых перечислителями. Вид спецификатора перечисления
заимствован у структур и объединений.

\begin{ShortGramDecsWithCC}{\\\[\]}
\textit[переч-спецификатор:]
     enum \textit[идентификатор\textsubscript[необ]]\
{ \textit[список-перечислителей] }
     enum \textit[идентификатор]

\textit[список-перечислителей:]
     \textit[перечислитель]
     \textit[список-перечислителей] , \textit[перечислитель]

\textit[перечислитель:]
     \textit[идентификатор]
     \textit[идентификатор] = \textit[константное-выражение]
\end{ShortGramDecsWithCC}

\noindent Идентификаторы, входящие в список перечислителей, объявляются
константами типа \verb|int| и могут употребляться везде, где требуется
константа. Если в этом списке нет ни одного перечислителя со знаком \verb|=|, то
значения констант начинаются с $0$ и увеличиваются на $1$ по мере чтения
декларации слева направо. Перечислитель со знаком \verb|=| даёт соответствующему
идентификатору значение; последующие идентификаторы продолжают прогрессию от
заданного значения.

Имена перечислителей, используемые в одной области действия, должны отличаться
друг от друга и от имён обычных переменных, однако их значения могут и
совпадать.

Роль идентификатора в \textit{переч-спецификаторе} аналогична роли тега
структуры в \textit{структ-спецификаторе}: он является именем некоторого
конкретного перечисления. Правила для списков и \textit{переч-спецификаторов} (с
тегами и без) те же, что и для спецификаторов структур или объединений, с той
лишь оговоркой, что элементы перечислений не бывают незавершённого типа; тег
\textit{переч-спецификатора} без списка перечислителей должен отсылать в
пределах области действия на спецификатор со списком.

\begin{ApxComment}
В первом издании языка перечислений не было, но они уже несколько лет
применяются.
\end{ApxComment}
\index{тег!перечисления|)}%
\index{перечисление!тег|)}%
\index{перечисление!константа|)}%
\index{константа!перечисления|)}%



\subsection{Деклараторы}
\label{apx:subsec:declarators}

\index{декларатор|(}%
Деклараторы имеют следующий синтаксис:

\begin{LongGramDecsWithCC}{\\\{\}}
\textit{декларатор:}
     \textit{указатель\textsubscript{необ}} \textit{собственно-декларатор}

\textit{собственно-декларатор:}
     \textit{идентификатор}
     ( \textit{декларатор} )
     \textit{собственно-декларатор}\
[ \textit{константное-выражение\textsubscript{необ}} ]
     \textit{собственно-декларатор}\
( \textit{список-типов-параметров} )
     \textit{собственно-декларатор}\
( \textit{список-идентификаторов\textsubscript{необ}} )

\textit{указатель:}
     * \textit{список-квалификаторов-типа\textsubscript{необ}}
     * \textit{список-квалификаторов-типа\textsubscript{необ}}\
\textit{указатель}

\textit{список-квалификаторов-типа:}
     \textit{квалификатор-типа}
     \textit{список-квалификаторов-типа} \textit{квалификатор-типа}
\end{LongGramDecsWithCC}

\noindent У структуры декларатора много сходных черт со структурой подвыражений,
поскольку в деклараторе, как и в подвыражении, допускаются операции раскрытия
указателя, обращения к функции и получения элемента массива (с тем же порядком
применения).

\subsection{Что означают деклараторы}
\label{apx:subsec:what_declarators_mean}

\index{декларация!типа}%
\index{тип!декларация}%
Список деклараторов располагается сразу после спецификаторов типа и указателя
класса памяти. Главный элемент любого декларатора -- это объявляемый им
идентификатор; в простейшем случае декларатор из одного его и состоит, что
отражено в первой строке продукции грамматики с именем
\textit{собственно-декларатор}. Спецификаторы класса памяти относятся
непосредственно к идентификатору, а его тип зависит от вида декларатора.
Декларатор следует воспринимать как утверждение: если в выражении идентификатор
появляется в том же контексте, что и в деклараторе, то он обозначает объект
специфицируемого типа.

Если соединить спецификаторы декларации, относящиеся к
типу~(\ref{apx:subsec:type_specifiers})‚ и некоторый конкретный декларатор, то
декларация примет следующий вид: <<\verb|T D|>>, где \verb|T| -- тип, а \verb|D|
-- декларатор. Эта запись описывает тип для идентификатора любого декларатора
индуктивно.

В декларации \verb|T D|, где \verb|D| -- просто идентификатор, тип
идентификатора есть \verb|T|.

В декларации \verb|T D|, где \verb|D| имеет вид

\begin{ShortCodePar}
( D1 )
\end{ShortCodePar}

\noindent тип идентификатора в \verb|D1| тот же, что и в \verb|D|. Скобки не
изменяют тип, но могут повлиять на результаты его <<привязки>> к идентификаторам
в сложных деклараторах.

\subsubsection{Деклараторы указателей}

\index{декларация!указателя}%
\index{структура!указатель на неё}%
\index{указатель!декларация}%
В декларации \verb|T D|, где \verb|D| имеет вид

\begin{ShortGramDecsWithCC}{\\\{\}}
* \textit{список-квалификаторов-типа\textsubscript{необ}} D1
\end{ShortGramDecsWithCC}

\noindent а тип идентификатора декларации \verb|T D1| есть
<<\textit{модификатор-типа} \verb|T|>>, тип идентификатора \verb|D| есть
<<\textit{модификатор-типа} \textit{список-квалификаторов-типа} указатель на
\verb|T|>>. Квалификаторы, следующие за \verb|*|, относятся к самому указателю,
а не к объекту, на который он указывает.

Рассмотрим, например, декларацию

\begin{ShortCodePar}
int *ap[];
\end{ShortCodePar}

\noindent Здесь \verb|ap[]| играет роль \verb|D1|; декларацию
<<\verb|int ap[]|>> следует расшифровать (см. ниже) как
<<массив из \verb|int|>>; список квалификаторов типа здесь пуст, а модификатор
типа есть <<массив из>>. Следовательно, на самом деле декларация \verb|ap|
гласит: <<массив из указателей на \verb|int|>>.

Вот ещё примеры деклараций:

\begin{ShortCodePar}
int i, *pi, *const cpi = &i;
const int ci = 3, *pci;
\end{ShortCodePar}

\noindent В них объявляются целое \verb|i| и указатель на целое \verb|pi|.
Значение указателя \verb|cpi| неизменно; \verb|cpi| всегда будет указывать в
одно и то же место, даже если значение, на которое он ссылается, станет иным.
Целое \verb|ci| есть константа, оно измениться не может (хотя может
инициализироваться, как в данном случае). Тип указателя \verb|pci| произносится
как <<указатель на \verb|const int|>>; сам указатель возможно изменить; при этом
он будет ссылаться на другое место, но значение, на которое он будет указывать,
посредством \verb|pci| изменить нельзя.

\subsubsection{Деклараторы массивов}
\label{apx:subsubsec:declarators_of_arrays}

\index{массив!декларация}%
\index{массив!декларатор}%
\index{декларатор!массива}%
\index{декларация!массива}%
В декларации \verb|T D|, где \verb|D| имеет вид

\begin{ShortGramDecsWithCC}{\\\{\}}
D1 [ \textit{константное-выражение\textsubscript{необ}} ]
\end{ShortGramDecsWithCC}

\noindent и где тип идентификатора декларации \verb|T D1| есть
<<\textit{модификатор-типа} \verb|T|>>, тип идентификатора \verb|D| есть
<<\textit{модификатор-типа} массив из \verb|T|>>. Если константное выражение
присутствует, то оно должно быть целочисленным и больше $0$. Если константное
выражение, специфицирующее количество элементов в массиве, отсутствует, то
массив имеет незавершённый тип.

Массив можно конструировать из объектов арифметического типа, указателей,
структур и объединений, а также других массивов (генерируя при этом многомерные
массивы). Любой тип, из которого конструируется массив, должен быть завершённым,
он не может быть, например, структурой или массивом незавершённого типа.
\index{массив!многомерный}%
Это значит, что для многомерного массива пустой может быть только первая
размерность. Незавершённый тип массива получает своё завершение либо в другой
декларации этого массива~(\ref{apx:subsec:external_declarations}), либо при его
инициализации~(\ref{apx:subsec:initialization}). Например, запись

\begin{ShortCodePar}
float fa[17], *afp[17];
\end{ShortCodePar}

\noindent декларирует массив из \verb|float|-чисел и массив из указателей на
\verb|float|-числа. Аналогично

\begin{ShortCodePar}
static int x3d[3][5][7];
\end{ShortCodePar}

\noindent декларирует статический трёхмерный массив целых размера
$3\times5\times7$. На самом деле, если быть точными, \verb|x3d| является
массивом из трёх элементов, каждый из которых есть массив из пяти элементов,
содержащих по 7 целых.

\index{массив!порядок элементов в памяти}%
\index{индексирование массива}%
\index{указатели!и индексирование}%
Операция индексирования \verb|E1[E2]| определена так, что она идентична операции
\verb|*(E1+E2)|. Следовательно, несмотря на асимметричность записи,
индексирование -- коммутативная операция. Учитывая правила преобразования,
применяемые для оператора \verb|+| и
массивов~(\ref{apx:subsec:pointers_and_integers},~\ref{apx:subsec:generation_of_pointer},~\ref{apx:subsec:additive_operators}),
можно сказать, что если \verb|E1| -- массив, а \verb|E2| -- целое, то
\verb|E1[E2]| обозначает \verb|E2|-й элемент массива \verb|E1|.
%
% исправлена орфографическая ошибка
% в оригинале было ``ассиметричность''
%

\index{индексирование массива!и указатели}%
Так, \verb|x3d[i][j][k]| означает то же самое, что и \verb|*(x3d[i][j] + k)|.
Первое подвыражение, \verb|x3d[i][j]|,
согласно~\ref{apx:subsec:generation_of_pointer} приводится к типу <<указатель на
массив целых>>; по~\ref{apx:subsec:additive_operators} сложение включает
умножение на размер объекта типа \verb|int|. Из этих же правил следует, что
массивы запоминаются <<построчно>> (последние индексы меняются чаще) и что
первая размерность в декларации помогает определить количество памяти,
занимаемой массивом, однако в вычислении адреса элемента массива участия не
принимает.

\subsubsection{Деклараторы функций}
\label{apx:subsubsec:declarators_of_functions}

\index{декларатор!функции}%
\index{декларация!функции}%
\index{список!аргументов переменной длины}%
\index{функция}%
\index{функция!декларация}%
При новом способе декларация функции \verb|T D|, где \verb|D| имеет вид

\begin{ShortGramDecsWithCC}{\\\{\}}
D1(\textit{список-типов-параметров})
\end{ShortGramDecsWithCC}

\noindent и тип идентификатора декларации \verb|T D1| есть
<<\textit{модификатор-типа} \verb|T|>>, тип идентификатора в \verb|D| есть
<<\textit{модификатор-типа} функция с аргументами
\textit{список-типов-параметров}, возвращающая \verb|T|>>.

Параметры имеют следующий синтаксис:

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{список-типов-параметров:}
     \textit{список-параметров}
     \textit{список-параметров} , ...

\textit{список-параметров:}
     \textit{декларация-параметра}
     \textit{список-параметров} , \textit{декларация-параметра}

\textit{декларация-параметра:}
     \textit{спецификаторы-декларации} \textit{декларатор}
     \textit{спецификаторы-декларации}\
\textit{абстрактный-декларатор\textsubscript{необ}}
\end{ShortGramDecsWithCC}

\noindent%
\index{void@\texttt{void}!список аргументов}%
При новом способе описания функций список параметров специфицирует их типы, а
если функция вообще не имеет параметров, на месте списка типов указывается одно
слово -- \verb|void|. Если список типов параметров заканчивается многоточием
<<\verb|, ...|>>, то функция может иметь больше аргументов, чем число явно
описанных параметров.~(См.~\ref{apx:subsubsec:function_call}.)

Типы параметров, являющихся массивами и функциями, заменяются на указатели в
соответствии с правилами преобразования
параметров~(\ref{apx:subsec:definitions_of_functions}). Единственный
спецификатор класса памяти, который разрешён в декларации параметра, -- это
\verb|register|, однако он игнорируется, если декларатор функции не является
заголовком её определения. Аналогично, если деклараторы в декларациях параметров
содержат идентификаторы, а декларатор функции не является заголовком определения
функции, то эти идентификаторы тотчас же выводятся из текущей области действия.

При старом способе декларация функции \verb|T D|, где \verb|D| имеет вид

\begin{ShortGramDecsWithCC}{\\\{\}}
D1(\textit{список-идентификаторов\textsubscript{необ}})
\end{ShortGramDecsWithCC}

\noindent и тип идентификатора декларации \verb|T D1| есть
<<\textit{модификатор-типа} \verb|T|>>, тип идентификатора в \verb|D| есть
<<\textit{модификатор-типа} функция от неспецифицированных аргументов,
возвращающая \verb|T|>>. Параметры, если они есть, имеют следующий вид:

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{список-идентификаторов:}
     \textit{идентификатор}
     \textit{список-идентификаторов} , \textit{идентификатор}
\end{ShortGramDecsWithCC}

\noindent При старом способе, если декларатор функции не используется в качестве
заголовка определения функции~(\ref{apx:subsec:definitions_of_functions}),
список идентификаторов должен отсутствовать. Никакой информации о типах
параметров в декларации не содержится.

Например, декларация

\begin{ShortCodePar}
int f(), *fpi(), (*pfi)();
\end{ShortCodePar}

\noindent описывает функцию \verb|f|, возвращающую целое, функцию \verb|fpi|,
возвращающую указатель на целое, и указатель \verb|pfi| на функцию, возвращающую
целое. Ни для одной функции в декларации не указаны типы параметров; все функции
описаны старым способом.

Вот как выглядит декларация в новой записи:

\begin{ShortCodePar}
int strcpy(char *dest, const char *source), rand(void);
\end{ShortCodePar}

\noindent Здесь \verb|strcpy| -- функция с двумя аргументами,
возвращающая значение типа \verb|int|; первый аргумент -- указатель на значение
типа \verb|char|, а второй -- указатель на неизменяющееся значение типа
\verb|char|. Имена параметров играют роль хороших комментариев. Вторая функция,
\verb|rand|, аргументов не имеет и возвращает \verb|int|.

\begin{ApxComment}
Прототипы деклараторов функций с параметрами -- наиболее важное нововведение
ANSI-стандарта. В сравнении со старым способом, принятым в первой редакции
языка, они позволяют проверять и приводить к нужному типу аргументы во всех
вызовах. Следует однако отметить, что их введение привнесло в язык некоторую
сумятицу и необходимость согласования обеих форм. Чтобы обеспечить
совместимость, потребовались некоторые <<синтаксические уродства>> типа
\verb|void| для явного указания на отсутствие параметров.

{\setlength{\parindent}{0.0604762\paperwidth}
%
% TODO: привести окружение в соответствие с требованиями данного блока
%
Многоточие <<\verb|, ...|>> применительно к функциям с варьируемым числом
аргументов -- также новинка, которая вместе со стандартным головным файлом
макросов \verb|<stdarg.h>| формализует неофициально используемый, но официально
запрещённый в первой редакции механизм.

Указанные способы записи заимствованы из языка Си++.
}
\end{ApxComment}
\index{декларатор|)}%
\index{декларация|)}%


\subsection{Инициализация}
\label{apx:subsec:initialization}

\index{инициализатор|(}%
\index{инициализация}%
\index{инициализация!переменных!автоматических}%
\index{инициализация!переменных!внешних}%
\index{инициализация!переменных!статических}%
При помощи \textit{иниц-декларатора} можно указать начальное значение
декларируемого объекта.
\index{фигурные скобки}%
Инициализатору, представляющему собой выражение или список инициализаторов,
заключённый в фигурные скобки, предшествует знак \verb|=|. Этот список может
завершаться запятой; её назначение -- сделать форматирование более чётким.

\begin{ShortGramDecsWithCC}{\\\[\]}
\textit[инициализатор:]
     \textit[выражение-присваивания]
     { \textit[список-инициализаторов] }
     { \textit[список-инициализаторов] , }

\textit[список-инициализаторов:]
     \textit[инициализатор]
     \textit[список-инициализаторов] , \textit[инициализатор]
\end{ShortGramDecsWithCC}

В инициализаторе статического объекта или массива все выражения должны быть
константными~(\ref{apx:subsec:constant_expressions}). Если инициализатор
\verb|auto|- и \verb|register|-объекта или массива находится в списке,
заключённом в фигурные скобки, то входящие в него выражения также должны быть
константными. Однако в случае автоматического объекта с одним выражением
инициализатор не обязан быть константным выражением, он просто должен иметь тип,
соответствующий объекту.

\begin{ApxComment}
В первой редакции не разрешалась инициализация автоматических структур,
объединений и массивов. ANSI-стандарт позволяет это; однако, если инициализатор
не может быть представлен одним простым выражением, инициализация может быть
выполнена только при помощи константных конструкций.
\end{ApxComment}

\index{инициализация!по умолчанию}%
\index{по умолчанию!инициализация}%
Статический объект, инициализация которого явно не указана, инициализируется
так, как если бы ему (или его членам) присваивалась константа $0$. Начальное
значение автоматического объекта, явным образом не инициализированного, не
определено.

Инициализатор указателя или объекта арифметического типа -- это единичное
выражение (возможно, заключённое в фигурные скобки), которое присваивается
объекту.

\index{инициализация!структуры}%
\index{структура!инициализация|(}%
Инициализатор структуры -- это либо выражение того же структурного типа, либо
заключённые в фигурные скобки инициализаторы её членов, заданные по порядку.
Безымянные поля битов игнорируются и не инициализируются. Если инициализаторов в
списке меньше, чем членов, то оставшиеся члены инициализируются нулём.
Инициализаторов не должно быть больше числа членов.

\index{инициализация!массива}%
Инициализатор массива -- это список инициализаторов его членов, заключённый в
фигурные скобки. Если размер массива не известен, то он считается равным числу
инициализаторов, при этом тип его становится завершённым. Если размер массива
известен, то число инициализаторов не должно превышать числа его членов; если
инициализаторов меньше, оставшиеся члены обнуляются.

Как особый выделен случай инициализации массива литер. Последний можно
инициализировать при помощи стрингового литерала; литеры инициализируют члены 
массива в том порядке, в каком они заданы в стринговом литерале. Точно так же,
при помощи литерала из расширенного набора
литер~(\ref{apx:subsec:string_literals})‚ можно инициализировать массив типа
\verb|wchar_t|. Если размер массива не известен, то он определяется числом
литер стринга, включающим и завершающую \verb|null|-литеру; если размер массива
известен, то число литер стринга, не считая завершающей \verb|null|-литеры, не
должно превышать его размера.

\index{инициализация!объединения}%
Инициализатором объединения может быть либо выражение того же типа, либо
заключённый в фигурные скобки инициализатор его первого члена.

\begin{ApxComment}
В первой редакции не позволялось инициализировать объединения. Правило <<первого
члена>> не отличается изяществом, однако не требует нового синтаксиса. Стандарт
ANSI проясняет ещё и семантику не инициализируемых явно объединений.
\end{ApxComment}

\index{инициализация!структуры}%
Введём для структуры и массива обобщённое имя: \emph{агрегат}. Если агрегат
содержит члены агрегатного типа, то правила инициализации применяются
рекурсивно. Фигурные скобки в некоторых случаях инициализации можно опускать.
Если инициализатор члена агрегата, который сам является агрегатом, начинается с
левой фигурной скобки, то этот подагрегат инициализируется последующим списком
разделённых запятыми инициализаторов; считается ошибкой, если количество
инициализаторов подагрегата превышает число его членов. Если, однако,
инициализатор подагрегата не начинается с левой фигурной скобки, то, чтобы его
инициализировать, нужно отсчитать соответствующее число элементов из списка; при
этом остальные члены инициализируются следующими инициализаторами агрегата, для
которого данный подагрегат является частью.
\index{структура!инициализация|)}%


Например,

\begin{ShortCodePar}
int x[] = { 1, 3, 5 };
\end{ShortCodePar}

\noindent декларирует и инициализирует \verb|x| как одномерный массив с тремя
членами, поскольку размера указано не было, а список состоит из трёх
инициализаторов.

\index{инициализация!двухмерных массивов|(}%
\index{массив!двумерный}%
\begin{ShortCodePar}
float y[4][3] = {
    { 1, 3, 5 },
    { 2, 4, 6 },
    { 3, 5, 7 },
};
\end{ShortCodePar}

\noindent представляет собой инициализацию с полным набором фигурных скобок:
$1$, $3$ и $5$ инициализируют первую строку в массиве \verb|y[0]|‚ т.е.
\verb|y[0][0]|, \verb|y[0][1]| и \verb|y[0][2]|. Аналогично инициализируются
следующие две строки: \verb|y[1]| и \verb|y[2]|. Инициализаторов не хватило на
весь массив, поэтому элементы строки \verb|y[3]| будут нулевыми. В точности тот
же результат был бы достигнут при помощи следующей декларации:

\begin{ShortCodePar}
float y[4][3] = {
    1, 3, 5, 2, 4, 6, 3, 5, 7
};
\end{ShortCodePar}

\noindent%
\index{инициализация!массива}%
Инициализатор для \verb|y| начинается с левой фигурной скобки, но для
\verb|y[0]| скобки нет, поэтому из списка будут взяты три элемента. Аналогично
по три элемента будут взяты для \verb|y[1]|, а затем и для \verb|y[2]|. В

\begin{ShortCodePar}
float y[4][3] = {
    { 1 }, { 2 }, { 3 }, { 4 }
};
\end{ShortCodePar}

\noindent инициализируется первый столбец матрицы \verb|y|, все же другие
элементы остаются нулевыми.
\index{инициализация!двухмерных массивов|)}%


\index{инициализация!стринговой константой}%
Наконец,

\begin{ShortCodePar}
char msg[] = "Синтаксическая ошибка в строке %s\n";
\end{ShortCodePar}

\noindent представляет собой пример массива литер, члены которого
инициализируются при помощи стринга; в его размере учитывается и завершающая
\verb|null|-литера.
\index{инициализатор|)}%


\subsection{Имена типов}
\label{apx:subsec:names_of_types}

\index{декларатор!абстрактный}%
\index{оператор!приведения к типу}%
\index{тип!имя}%
В ряде случаев возникает потребность в применении имени типа данных (например,
при явном приведении к типу, в указании типов параметров внутри деклараций
функций, в аргументе оператора \verb|sizeof|). Эта потребность реализуется при
помощи \emph{имени типа}, определение которого синтаксически почти совпадает с
декларацией объекта того же типа. Оно отличается от последней лишь тем, что не
содержит имени объекта.

{\setlength{\codeIndent}{\codeIndentBk-2.25em}
\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{имя-типа:}
     \textit{список-спецификаторов-квалификаторов}\
\textit{абстрактный-декларатор\textsubscript{необ}}

\textit{абстрактный-декларатор:}
     \textit{указатель}
     \textit{указатель\textsubscript{необ}}\
\textit{собственно-абстрактный-декларатор}

\textit{собственно-абстрактный-декларатор:}
     ( \textit{абстрактный-декларатор} )
     \textit{собственно-абстрактный-декларатор\textsubscript{необ}}\
[ \textit{константное-выражение\textsubscript{необ}} ]
     \textit{собственно-абстрактный-декларатор\textsubscript{необ}}\
( \textit{список-типов-параметров\textsubscript{необ}} )
\end{ShortGramDecsWithCC}
\setlength{\codeIndent}{\codeIndentBk}}

\noindent Можно указать одно-единственное место в абстрактном деклараторе, где
мог бы оказаться идентификатор, если бы приведённая конструкция была полноценным
декларатором. Именованный тип совпадает с типом этого <<невидимого
идентификатора>>. Например,

\begin{ShortCodePar}
int
int *
int *[3]
int (*)[]
int *()
int (*[])(void)
\end{ShortCodePar}

\noindent соответственно обозначают типы <<целое>>, <<указатель на целое>>,
<<массив из трёх указателей на целое>>, <<указатель на массив из неизвестного
количества целых>>, <<функция неизвестного количества параметров, возвращающая
указатель на целое>>, <<массив неизвестного количества указателей на функции без
параметров, каждая из которых возвращает целое>>.

\subsection{Декларация
\texorpdfstring{\protect\Verb|typedef|}{typedef}}
\label{apx:subsec:typedef_declaration}

\index{декларация!typedef@\texttt{typedef}}%
\index{typedef-декларация@\texttt{typedef}-декларация}%
Декларации, в которых спецификатор класса памяти есть \verb|typedef|, не
декларируют объекты -- они определяют идентификаторы, представляющие собой имена
типов. Эти идентификаторы называются \textit{typedef-именами}.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{typedef-имя:}
     \textit{идентификатор}
\end{ShortGramDecsWithCC}

\noindent Декларация \verb|typedef| приписывает тип каждому имени своего
декларатора обычным способом.~(См.~\ref{apx:subsec:what_declarators_mean}.) С
этого момента \textit{typedef-имя} синтаксически эквивалентно ключевому слову
спецификатора типа, обозначающему связанный с ним тип. Например, после

\begin{ShortCodePar}
typedef long Blockno, *Blockptr;
typedef struct { double r, theta; } Complex;
\end{ShortCodePar}
%
% исправлена опечатка
% в оригинале одна левая скобка была круглой
%

\noindent допустимы следующие декларации:

\begin{ShortCodePar}
Blockno b;
extern Blockptr bp;
Complex z, *zp;
\end{ShortCodePar}

\noindent Тип \verb|b| есть \verb|long|, тип \verb|bp| -- <<указатель на
\verb|long|>>, тип \verb|z| -- структура заданного вида, а \verb|zp| --
указатель на такую структуру.

Декларация \verb|typedef| не вводит новых типов, она только даёт имена типам,
которые могли бы быть специфицированы и другим способом. Например, \verb|b|
имеет тот же тип, что и любой другой \verb|long|-объект.

\textit{Typedef-имена} могут быть перекрыты другими определениями во внутренней
области действия, но при условии, что в них присутствует указание типа.
Например,

\begin{ShortCodePar}
extern Blockno;
\end{ShortCodePar}

\noindent не переопределяет \verb|Blockno|‚ а вот

\begin{ShortCodePar}
extern int Blockno;
\end{ShortCodePar}

\noindent переопределяет.

\subsection{Эквивалентность типов}
\label{apx:subsec:type_equvalency}

\index{тип!эквивалентность}%
\index{эквивалентность типов}%
Два списка спецификаторов типа эквивалентны, если они содержат одинаковый их
набор с учётом синонимичности названий (например, \verb|long| и \verb|long int|
считаются одинаковыми типами). Структуры, объединения и перечисления с разными
тегами считаются разными, а каждое безтеговое объединение, структура или
перечисление представляет собой уникальный тип.

Два типа считаются совпадающими, если их абстрактные
деклараторы~(\ref{apx:subsec:names_of_types}) после замены всех
\textit{typedef-имён} их типами и выбрасывания имён параметров функций составят
эквивалентные списки спецификаторов типов. При сравнении учитываются размеры
массивов и типы параметров функций.

\section{Инструкции}

\index{инструкции|(}%
\index{инструкции!последовательность выполнения}%
\index{порядок!выполнения инструкций}%
За исключением оговорённых случаев инструкции выполняются в том порядке, как они
написаны. Инструкции не имеют значений и выполняются, чтобы произвести
определённые действия. Все виды инструкций можно разбить на несколько групп:

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{инструкция:}
     \textit{помеченная-инструкция}
     \textit{инструкция-выражение}
     \textit{составная-инструкция}
     \textit{инструкция-выбора}
     \textit{циклическая-инструкция}
     \textit{инструкция-перехода}
\end{ShortGramDecsWithCC}

\subsection{Помеченные инструкции}
\label{apx:subsec:labeled_instructions}

\index{метка!case@\texttt{case}}%
\index{метка!default@\texttt{default}}%
\index{метка}%
\index{инструкция!помеченная}%
\index{case-метка@\texttt{case}-метка}%
\index{default@\texttt{default}}%
Инструкции может предшествовать метка.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{помеченная-инструкция:}
     \textit{идентификатор} : \textit{инструкция}
     case \textit{константное-выражение} : \textit{инструкция}
     default : \textit{инструкция}
\end{ShortGramDecsWithCC}

\noindent Метка, состоящая из идентификатора, одновременно служит и декларацией
этого идентификатора. Единственное назначение идентификатора-метки -- указать
место перехода для \verb|goto|.
\index{метка!область действия}%
\index{область действия!меток}%
Областью действия идентификатора-метки является текущая функция. Так как метки
имеют своё собственное пространство имён, они не <<конфликтуют>> с другими
идентификаторами и не могут быть
перекрыты.~(См.~\ref{apx:subsec:lexical_scope}.)

\verb|case|-метки и \verb|default|-метки используются в инструкции
\verb|switch|~(\ref{apx:subsec:choice_instruction}). Константное выражение в
\verb|case| должно быть целочисленным.

Сами по себе метки не изменяют порядка вычислений.

\subsection{Инструкция-выражение}
\label{apx:subsec:statement-expression}

\index{выражение-инструкция}%
\index{точка с запятой}%
Наиболее употребительный вид инструкции -- это \textit{инструкция-выражение}.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{инструкция-выражение:}
     \textit{выражение\textsubscript{необ}} ;
\end{ShortGramDecsWithCC}

\noindent Чаще всего \textit{инструкция-выражение} -- это присваивание или
вызов функции. Все действия, реализующие побочный эффект выражения,
завершаются, прежде чем начинает выполняться следующая инструкция.
\index{инструкция!пустая}%
Если выражение в инструкции опущено, то она называется пустой; пустая инструкция
часто используется для обозначения пустого тела циклической инструкции или в
качестве места для метки.

\subsection{Составная инструкция}
\label{apx:subsec:composit_instruction}

\index{блок}%
\index{блок!структура}%
\index{составная инструкция}%
\index{инструкция!составная}%
\index{фигурные скобки}%
Так как в местах, где по синтаксису полагается одна инструкция, иногда возникает
необходимость выполнить несколько, предусматривается возможность задания
составной инструкции (которую также называют блоком). Тело определения функции
есть составная инструкция:

\begin{ShortGramDecsWithCC}{\\\[\]}
\textit[составная-инструкция:]
    { \textit[список-деклараций\textsubscript[необ]]\
\textit[список-инструкций\textsubscript[необ]] }

\textit[список-деклараций:]
     \textit[декларация]
     \textit[список-деклараций] \textit[декларация]

\textit[список-инструкций:]
     \textit[инструкция]
     \textit[список-инструкций] \textit[инструкция]
\end{ShortGramDecsWithCC}

\noindent%
\index{блок!структура}%
Если идентификатор из списка деклараций находился в области действия объемлющего
блока, то действие внешней декларации при входе внутрь данного блока
приостанавливается~(\ref{apx:subsec:lexical_scope})‚ а после выхода из него
возобновляется. Внутри блока идентификатор может быть декларирован только один
раз. Для каждого отдельного пространства имён эти правила действуют
независимо~(\ref{apx:sec:scope}); идентификаторы из разных пространств имён
всегда различны.

\index{блок!инициализация}%
\index{инициализация!в блоке}%
Инициализация автоматических объектов осуществляется при каждом входе в блок и
продолжается по мере продвижения по деклараторам. При передаче управления внутрь
блока инициализации не выполняются. Инициализации статических объектов
осуществляются только один раз перед запуском программы.

\subsection{Инструкции выбора}
\label{apx:subsec:choice_instruction}

\index{инструкции!выбора}%
\index{if-else@\texttt{if-else}!инструкция}%
\index{switch-инструкция@\texttt{switch}-инструкция}%
Инструкции выбора осуществляют отбор одной из нескольких альтернатив,
определяющих порядок выполнения инструкций.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{инструкция-выбора:}
     if ( \textit{выражение} ) \textit{инструкция}
     if ( \textit{выражение} ) \textit{инструкция} else \textit{инструкция}
     switch ( \textit{выражение} ) \textit{инструкция}
\end{ShortGramDecsWithCC}

Оба вида \verb|if|-инструкций содержат выражение, которое должно иметь
арифметический тип или тип указателя. Сначала вычисляется выражение со всеми его
побочными эффектами, результат сравнивается с $0$. В случае несовпадения с $0$
выполняется первая подинструкция. В случае совпадения с $0$ для второго типа
\verb|if| выполняется вторая подинструкция.
\index{неоднозначность \texttt{if-else}}%
\index{if-else@\texttt{if-else}!неоднозначность}%
Связанная со словом \verb|else| неоднозначность разрешается тем, что слово
\verb|else| соотносят с последней не имеющей \verb|else| \verb|if|-инструкцией‚
расположенной в одном с этим \verb|else| блоке и на одном уровне вложенности
блоков.

Инструкция \verb|switch| вызывает передачу управления на одну из нескольких
инструкций в зависимости от значения выражения, которое должно иметь
целочисленный тип. Управляемая при помощи \verb|switch| подинструкция обычно
составная. Любая инструкция внутри этой подинструкции может быть помечена одной
или несколькими \verb|case|-метками~(\ref{apx:subsec:labeled_instructions}).
Управляющее выражение подвергается целочисленному
повышению~(\ref{apx:subsec:integral_promotion}),
а \verb|case|-константы приводятся к повышенному типу. После такого
преобразования никакие две \verb|case|-константы в одной инструкции
\verb|switch| не должны иметь одинаковых значений. Со \verb|switch|-инструкцией
может быть связано не более одной \verb|default|-метки. Конструкции
\verb|switch| допускается вкладывать друг в друга; \verb|case| и
\verb|default|-метки относятся к самой внутренней \verb|switch|-инструкции из
тех, которые их содержат.

Инструкция \verb|switch| выполняется следующим образом. Вычисляется выражение со
всеми побочными эффектами, и результат сравнивается с каждой
\verb|case|-константой. Если одна из \verb|case|-констант равна значению
выражения, управление переходит на инструкцию с соответствующей
\verb|case|-меткой. Если ни с одной из \verb|case|-констант нет совпадения,
управление передаётся на инструкцию с \verb|default|-меткой, если такая имеется,
в противном случае ни одна из подинструкций \verb|switch| не выполняется.

\begin{ApxComment}
В первой редакции требовалось, чтобы выражение и \verb|case|-константы в
\verb|switch| были целого типа.
\end{ApxComment}

\subsection{Циклические инструкции}

\index{циклические инструкции}%
\index{do-инструкция@\texttt{do}-инструкция}%
\index{for@\texttt{for}!инструкция}%
\index{while@\texttt{while}!инструкция}%
Циклические инструкции специфицируют циклы.

{\setlength{\codeIndent}{\codeIndentBk-0.25em}%
\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{циклическая-инструкция:}
     while ( \textit{выражение} ) \textit{инструкция}
     do \textit{инструкция} while ( \textit{выражение} )
     for ( \textit{выражение\textsubscript{необ}} ;\
\textit{выражение\textsubscript{необ}} ;\
\textit{выражение\textsubscript{необ}} ) \textit{инструкция}
\end{ShortGramDecsWithCC}
\setlength{\codeIndent}{\codeIndentBk}}

В инструкциях \verb|while| и \verb|do| выполнение подинструкции повторяется до
тех пор, пока значение выражения не станет нулём. Выражение должно иметь
арифметический тип или тип указателя. В \verb|while| вычисление выражения со
всеми побочными эффектами и проверка осуществляются перед каждым выполнением
инструкции, а в \verb|do| -- после.

В инструкции \verb|for| первое выражение вычисляется один раз, тем самым
осуществляется инициализация цикла. На тип этого выражения никакие ограничения
не накладываются. Второе выражение должно иметь арифметический тип или тип
указателя; оно вычисляется перед каждой итерацией. Как только его значение
становится равным $0$, \verb|for| прекращает свою работу. Третье выражение
вычисляется после каждой итерации и, следовательно, выполняет повторную
инициализацию цикла. Никаких ограничений на его тип нет. Побочные эффекты всех
трёх выражений заканчиваются по завершении их вычислений. Если подинструкция не
содержит в себе \verb|continue|, то

\begin{ShortCodeParWithCC}{\\\{\}}
for ( \textit{выражение1} ; \textit{выражение2} ; \textit{выражение3} )\
\textit{инструкция}
\end{ShortCodeParWithCC}

\noindent эквивалентна конструкции

\begin{ShortCodeParWithCC}{\\\[\]}
\textit[выражение1] ;
while ( \textit[выражение2] ) {
    \textit[инструкция]
    \textit[выражение3] ;
}
\end{ShortCodeParWithCC}

Любое из трёх выражений цикла может быть опущено. Считается, что отсутствие
второго выражения равносильно сравнению с ненулевой константой.


\subsection{Инструкции перехода}

\index{инструкции!перехода}%
\index{break@\texttt{break}}%
\index{continue@\texttt{continue}}%
\index{goto-инструкция@\texttt{goto}-инструкция}%
Инструкции перехода осуществляют безусловную передачу управления.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{инструкция-перехода:}
     goto \textit{идентификатор} ;
     continue ;
     break ;
     return \textit{выражение\textsubscript{необ}} ;
\end{ShortGramDecsWithCC}

В \verb|goto|-инструкции идентификатор должен быть
меткой~(\ref{apx:subsec:labeled_instructions}), расположенной в текущей функции.
Управление передаётся на помеченную инструкцию.

Инструкцию \verb|continue| можно располагать только внутри цикла. Она вызывает
переход к следующей итерации самого внутреннего содержащего её цикла. Говоря
более точно, для каждой из конструкций

\smallskip
{\setlength{\LTleft}{\codeIndent-\tabcolsep}%
\SetLenVarWithVal{\Thirdlen}{(\linewidth-\LTleft-5\tabcolsep)/3}%
\noindent\hspace{\LTleft}\begin{tabular}
{p{\Thirdlen}p{\Thirdlen}p{\Thirdlen}}
\verb|while (...) {|&\verb|do {|&\verb|for (...) {|\\
\verb|    ...|&\verb|  ...|&\verb|     ...|   \\
\verb|contin: ;|&\verb|contin: ;|&\verb|contin: ;|  \\
\verb|}|&\verb|} while (...);|&\verb|}|
\end{tabular}}
\smallskip

\noindent инструкция \verb|continue|‚ если она не <<погружена>> в ещё более
внутренний цикл, делает то же самое, что и \verb|goto contin|.

Инструкция \verb|break| встречается в циклической или в
\verb|swhitch|-инструкции, и только в них. Она завершает работу самой внутренней
циклической или \verb|switch|-инструкции, содержащей \verb|break|, после чего
управление переходит к следующей инструкции.

\index{return-инструкция@\texttt{return}-инструкция}%
При помощи \verb|return| функция возвращает управление в программу, откуда она
была вызвана.
\index{преобразование!\texttt{return}-инструкцией}%
\index{тип!преобразование в \texttt{return}}%
\index{return@\texttt{return}!преобразование типа в}%
Если за \verb|return| следует выражение, то его значение возвращается вызвавшей
эту функцию программе. Значение выражения приводится к типу так, как если бы оно
присваивалось переменной, имеющей тот же тип, что и функция.

Ситуация, когда <<путь>> вычислений приводит в конец функции (т.е. на последнюю
закрывающую фигурную скобку), равносильна выполнению \verb|return|-инструкции
без выражения. В последнем случае, а также в случае явного задания \verb|return|
без выражения возвращаемое значение не определено.
\index{инструкции|)}%


\section{Внешние декларации}
\label{apx:sec:external_declarations}

\index{декларация!внешняя|(}%
\index{декларация!внешней переменной}%
\index{транслируемая компонента}%
То, что подготовлено в качестве ввода для Си-компилятора, называется компонентой
трансляции. Она состоит из последовательности внешних деклараций, каждая из
которых представляет собой либо декларацию, либо определение функции.

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{компонента-трансляции:}
     \textit{внешняя-декларация}
     \textit{компонента-трансляции} \textit{внешняя-декларация}

\textit{внешняя-декларация:}
     \textit{определение-функции}
     \textit{декларация}
\end{ShortGramDecsWithCC}

Область действия внешних деклараций простирается до конца компоненты трансляции,
в которой они декларированы, точно так же, как
\index{составная инструкция}%
\index{инструкция!составная}%
область действия деклараций в блоке распространяется до конца этого блока.
Синтаксис внешней декларации не отличается от синтаксиса любой другой декларации
за одним исключением: код функции можно определять только при помощи внешней
декларации.

\subsection{Определение функции}
\label{apx:subsec:definitions_of_functions}

\index{определение!функции}%
\index{функция!определение}%
Определение функции имеет следующий вид:

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{определение-функции:}
     \textit{спецификаторы-декларации\textsubscript{необ}}\
\textit{декларатор}
                          \textit{список-деклараций\textsubscript{необ}}\
\textit{составная-инструкция}
\end{ShortGramDecsWithCC}

\noindent Из спецификаторов класса памяти в \textit{спецификаторах-декларации}
возможны только \verb|extern| и \verb|static|; различия между последними
рассматриваются в~\ref{apx:subsec:links}.

Типом возвращаемого функцией значения может быть арифметический тип, структура,
объединение, указатель и \verb|void|, но не <<функция>> и не <<массив>>.
Декларатор в декларации функции должен явно указывать на то, что описываемый им
идентификатор имеет тип <<функция>>, т.е. он должен иметь одну из следующих двух
форм~(\ref{apx:subsubsec:declarators_of_functions}):

\begin{ShortGramDecsWithCC}{\\\{\}}
\textit{собственно-декларатор} ( \textit{список-типов-параметров} )
\textit{собственно-декларатор}\
( \textit{список-идентификаторов\textsubscript{необ}} )
\end{ShortGramDecsWithCC}

\noindent где \textit{собственно-декларатор} есть идентификатор или
идентификатор, заключённый в скобки. Заметим, что на тип <<функция>> посредством
\verb|typedef| ссылаться нельзя.

Первая форма соответствует определению функции новым способом, для которого
характерно декларирование параметров в \emph{списке-типов-параметров} вместе с
их типами; \textit{список-деклараций}, располагаемый за декларатором, должен
отсутствовать.
\index{void@\texttt{void}!список аргументов}%
Если \textit{список-типов-параметров} не состоит из одного-единственного слова
\verb|void|, показывающего, что параметров у функции нет, то в каждом
деклараторе в \textit{списке-типов-параметров} обязан присутствовать
идентификатор.
\index{список!аргументов переменной длины}%
Если \textit{список-типов-параметров} заканчивается знаками <<\verb|, ...|>>, то
вызов функции может иметь аргументов больше, чем параметров; в таком случае,
чтобы ссылаться на дополнительные аргументы, следует пользоваться механизмом
макроса \verb|va_arg| из головного файла \verb|<stdarg.h>|, описанного в
приложении~\ref{apx:stdlib}. Функции с переменным числом аргументов должны иметь
по крайней мере один именованный параметр.

Вторая форма -- определение функции старым способом.
\textit{Список-идентификаторов} содержит имена параметров, а
\textit{список-деклараций} приписывает им типы. В \textit{списке-деклараций}
разрешено декларировать только именованные параметры, инициализация запрещается,
и из спецификаторов класса памяти возможен только \verb|register|.

И в том и другом способе определения функции мыслится, что все параметры как бы
декларированы в самом начале составной инструкции, образующей тело функции, и
совпадающие с ними имена здесь декларироваться не должны (хотя, как и любые
идентификаторы, их можно переопределить в более внутренних блоках). Декларацию
параметра <<массив из \textit{тип}>> можно трактовать как <<указатель на
\textit{тип}>>; аналогично декларацию параметра <<функция, возвращающая
\textit{тип}>> -- как <<указатель на функцию, возвращающую \textit{тип}>>. В
момент вызова функции её аргументы соответствующим образом преобразуются и
присваиваются параметрам.~(См.~\ref{apx:subsubsec:function_call}.).

\begin{ApxComment}
Новый способ определения функций введён ANSI-стандартом. Есть также небольшие
изменения в операции повышения типа; в первой редакции параметры типа
\verb|float| следовало читать как \verb|double|. Различие между \verb|float| и
\verb|double| становилось заметным, лишь когда внутри функции генерировался
указатель на параметр.
\end{ApxComment}

Ниже приведён пример определения функции новым способом:

\begin{ShortCodePar}
int max(int a, int b, int c)
{
    int m;
    m = (a > b) ? a : b;
    return (m > c) ? m : c;
}
\end{ShortCodePar}

\noindent Здесь \verb|int| -- \textit{спецификаторы-декларации}; 
\verb|max(int a, int b, int c)| -- декларатор функции, а \verb|{ ... }| -- блок,
задающий её код. Определение старым способом той же функции выглядит следующим
образом:

\begin{ShortCodePar}
int max(a, b, c)
int a, b, c;
{
    /* ... */
}
\end{ShortCodePar}

\noindent где \verb|max(a, b, c)| -- декларатор, а \verb|int a, b, c| --
\textit{список-деклараций} для параметров.

\subsection{Внешние декларации}
\label{apx:subsec:external_declarations}

Внешние декларации специфицируют характеристики объектов, функций и других
идентификаторов. Термин <<внешний>> здесь используется, чтобы подчеркнуть тот
факт, что декларации расположены вне функций; впрямую с ключевым словом
\verb|extern| (<<внешний>>) он не связан. Класс памяти для объекта с внешней
декларацией либо вообще не указывается, либо специфицируется как \verb|extern|
или \verb|static|.

\index{транслируемая компонента}%
В одной компоненте трансляции для одного идентификатора может содержаться
несколько внешних деклараций, если они согласуются друг с другом по типу и
способу связи и если для этого идентификатора существует не более одного
определения.

Две декларации объекта или функции считаются согласованными по типу в
соответствии с правилами, рассмотренными в~\ref{apx:subsec:type_equvalency}.
Кроме того, если декларации отличаются лишь тем, что в одной из них тип
структуры, объединения или перечисления
незавершён~(\ref{apx:subsec:declaration_of_structures_and_unions}), а в другой
соответствующий ему тип с тем же тегом завершён, то такие типы считаются
согласованными. Если два типа
массива~(\ref{apx:subsubsec:declarators_of_arrays}) отличаются лишь тем, что
один завершённый, а другой незавершённый, то такие типы также считаются
согласованными. Наконец, если один тип специфицирует функцию старым способом, а
другой -- ту же функцию новым способом (с декларациями параметров), то такие
типы также считаются согласованными.

\index{связь!внешняя}%
\index{связь!внутренняя}%
Если первая внешняя декларация функции или объекта помечена спецификатором
\verb|static|, то у декларируемого идентификатора -- \emph{внутренняя связь}; в
противном случае у него -- \emph{внешняя связь}. Способы связей обсуждаются
в~\ref{apx:subsec:links}.

Внешняя декларация объекта считается определением, если она имеет инициализатор.
\index{определение!пробное}%
\index{пробное определение}%
Внешняя декларация, в которой нет инициализатора и нет спецификатора
\verb|extern|, считается \emph{пробным определением}. Если в компоненте
трансляции появится определение объекта, то все его пробные определения просто
станут избыточными декларациями. Если никакого определения для этого объекта в
компоненте трансляции не обнаружится, то все его пробные определения будут
трактоваться как одно определение с инициализатором $0$.

Каждый объект должен иметь ровно одно определение. Для объекта с внутренней
связью это правило относится к каждой отдельной компоненте трансляции, поскольку
объекты с внутренними связями в каждой компоненте уникальны. В случае объектов с
внешними связями указанное правило действует в отношении всей программы в целом.

\begin{ApxComment}
Хотя правило одного определения формулируется несколько иначе по сравнению с
первой редакцией, по существу оно совпадает с прежним. Некоторые реализации его
ослабляют, более широко трактуя понятие пробного определения. В другом варианте
указанного правила, который распространён в системах UNIX и признан как
общепринятое расширение стандарта, все пробные определения объектов с внешними
связями из всех транслируемых компонент программы рассматриваются вместе, а не
отдельно в каждой компоненте. Если где-то в программе обнаруживается
определение, то пробные определения становятся просто декларациями, но, если
никакого определения не встретилось, то все пробные определения становятся
одним-единственным определением с инициализатором $0$.
\end{ApxComment}
\index{декларация!внешняя|)}%


\section{Область действия и связи}
\label{apx:sec:scope}

\index{компиляция!раздельная}%
\index{область действия}%
Каждый раз компилировать всю программу целиком нет необходимости. Исходный текст
можно хранить в нескольких файлах, представляющих собой компоненты трансляции.
Ранее скомпилированные программы могут загружаться из библиотек. Связи между
функциями программы могут осуществляться через вызовы и внешние данные.

Следовательно, существуют два вида областей действия: первая -- это
\emph{лексическая область} идентификатора: т.е. область в тексте программы, где
имеют смысл все его характеристики;
\index{связь}%
вторая область -- это область, ассоциируемая с объектами и функциями, имеющими
внешние связи, устанавливаемые между идентификаторами из раздельно компилируемых
компонент трансляции.

\subsection{Лексическая область действия}
\label{apx:subsec:lexical_scope}

\index{лексическая область действия}%
\index{область действия!лексическая}%
\index{область действия!правила определения}%
Каждый идентификатор попадает в одно из нескольких
\index{именное пространство}%
пространств имён. Эти пространства никак не связаны друг с другом. Один и тот же
идентификатор может использоваться в разных смыслах даже в одной области
действия, если он принадлежит разным пространствам имён. Ниже через точку с
запятой перечислены классы объектов, имена которых представляют собой отдельные
независимые пространства: объекты, функции, \verb|typedef|-имена и
\verb|enum|-константы; метки инструкций; теги структур, объединений и
перечислений; члены каждой отдельной структуры или объединения.

\begin{ApxComment}
Сформулированные правила несколько отличаются от прежних, описанных в первом
издании. Метки инструкций не имели раньше собственного пространства; теги
структур и теги объединений (а в некоторых реализациях и теги перечислений)
имели отдельные пространства. Размещение тегов структур, объединений и
перечислений в одном общем пространстве -- это дополнительное ограничение,
которого раньше не было. Наиболее существенное отклонение от первой редакции в
том, что каждая отдельная структура (или объединение) создаёт своё собственное
пространство имён её членов. Таким образом, одно и то же имя может
использоваться в нескольких различных структурах. Это правило широко применяется
уже несколько лет.
\end{ApxComment}
%
% в оригинале в левом нижнем углу страницы надпись ``8. Заказ № 13''
%

\index{область действия!внешних объектов}%
\index{определение!внешней переменной}%
Лексическая область действия идентификатора объекта (или функции), объявленного
во внешней декларации, начинается с места, где заканчивается его декларатор, и
простирается до конца компоненты трансляции, в которой он декларирован. Область
действия параметра в определении функции начинается с начала блока,
представляющего собой тело функции, и распространяется на всю функцию; область
действия параметра в описании функции заканчивается в конце этого описания.
\index{область действия!автоматических переменных}%
Область действия идентификатора, декларируемого в начале блока, начинается от
места, где заканчивается его декларатор, и продолжается до конца этого блока.
\index{метка!область действия}%
\index{область действия!меток}%
Областью действия метки является вся функция, где эта метка встречается. Область
действия тега структуры, объединения или перечисления начинается от его
появления в спецификаторе типа и продолжается до конца компоненты трансляции для
декларации внешнего уровня и до конца блока для декларации внутри функции.

Если идентификатор явно декларирован в начале некоторого блока (в том числе тела
функции), то любая декларация того же идентификатора, находящаяся снаружи этого
блока, временно перестаёт действовать вплоть до конца блока.

\subsection{Связи}
\label{apx:subsec:links}

\index{связь}%
\index{связь!внешняя}%
\index{связь!внутренняя}%
Если встречается несколько деклараций, имеющих одинаковый идентификатор и
описывающих объект (или функцию), то все эти декларации в случае внешней связи
относятся к одному объекту (функции) -- уникальному для всей программы; если же
связь внутренняя, то свойство уникальности распространяется только на компоненту
трансляции.

\index{static-переменные@\texttt{static}-переменные!внешние}%
Как говорилось в~\ref{apx:subsec:external_declarations}‚ если первая внешняя
декларация имеет спецификатор \verb|static|, то она описывает идентификатор с
внутренней связью, если такого спецификатора нет, то с внешней связью. Если
декларация находится внутри блока и не содержит \verb|extern|, то
соответствующий идентификатор ни с чем не связан и уникален для данной функции.
Если декларация содержит \verb|extern| и блок находится в области действия
внешней декларации этого идентификатора, то последний имеет ту же связь и
ссылается на тот же объект (функцию). Однако, если ни одной внешней декларации
для этого идентификатора нет, то он имеет внешнюю связь.

\section{Препроцессирование}
\label{apx:sec:preprocessing}

\index{макро-процессор|(}%
\index{препроцессор|(}%
Препроцессор выполняет макроподстановку, условную компиляцию, включение
именованных файлов. Строки, начинающиеся со знака \verb|#| (перед которым
возможны пробельные литеры), устанавливают связь с препроцессором.
\index{транслируемая компонента}%
Их синтаксис не зависит от остальной части языка; они могут появляться где
угодно и оказывать влияние (независимо от области действия) вплоть до конца
транслируемой компоненты. Границы строк принимаются во внимание; каждая строка
анализируется отдельно (однако есть возможность <<склеивать>> строки,
см.~\ref{apx:subsec:concatenation_of_strings}). Лексемами для препроцессора
являются все лексемы языка и последовательности литер, задающие имена файлов,
как, например, в директиве \verb|#include|~(\ref{apx:subsec:file_include}).
Кроме того, любая литера, не определённая каким-либо другим способом,
воспринимается как лексема. Влияние пробельных литер, отличающихся от пробелов и
горизонтальных табуляций, внутри строк препроцессора не определено.

\index{порядок!трансляции}%
\index{трансляция!порядок}%
\index{трансляция!фазы}%
\index{фазы трансляции}%
Само препроцессирование проистекает в нескольких логически последовательных
фазах. В отдельных реализациях некоторые фазы объединены.

\begin{enumerate}
 \item Трёхзнаковые последовательности, описанные
 в~\ref{apx:subsec:trigraph_sequences}‚ заменяются их эквивалентами.
 \index{литера!новая-строка \texttt{\textbackslash n}}%
 \index{n@\texttt{\textbackslash n}}%
 Между  строками  вставляются литеры новая-строка, если того требует
 операционная система.
 \item
 \index{литера!новая-строка \texttt{\textbackslash n}}%
 \index{n@\texttt{\textbackslash n}}%
 Выбрасываются пары  литер, состоящие из обратной наклонной черты с последующей
 литерой новая-строка; тем самым осуществляется <<склеивание>>
 строк~(\ref{apx:subsec:concatenation_of_strings}).
 \item Программа разбивается на лексемы, разделённые литерами пропусков.
 \index{комментарий}%
 Комментарии заменяются на единичные пробелы. Затем выполняются директивы
 препроцессора и
 макроподстановки~(\ref{apx:subsec:macro_definition_and_expansion}--\ref{apx:subsec:predefined_names}).
 \item Эскейп-последовательности в литерных константах и стринговых
 литералах~(\ref{apx:subsubsec:character_constants}‚~\ref{apx:subsec:string_literals}) заменяются на литеры, которые они
 обозначают. Соседние стринговые литералы конкатенируются.
 \item Результат транслируется. Затем устанавливаются связи с другими
 программами и библиотеками посредством сбора необходимых программ и данных и
 соединения ссылок на внешние функции и объекты с их определениями.
\end{enumerate}

\subsection{Трёхзнаковые последовательности}
\label{apx:subsec:trigraph_sequences}

\index{литеры!набор!ASCII}%
\index{литеры!набор}%
\index{трёхзнаковые последовательности}%
\index{ASCII}%
Множество литер, из которых набираются исходные Си-программы, основано на
семибитовом ASCII-коде.
\index{литеры!набор!ISO 646-1983}%
\index{ISO}%
Однако он шире, чем инвариантный код литер ISO 646-1983 (ISO 646-1983 Invariant
Code Set). Чтобы дать возможность пользоваться сокращённым набором литер, все
указанные ниже трёхзнаковые последовательности заменяются на соответствующие им
единичные литеры. Замена осуществляется до любой иной обработки.

\begin{center}
\begin{tabular}{lll}
\verb|??=    #        |&\verb|??(    [        |&\verb|??<    {        |\\
\verb|??/    \        |&\verb|??)    ]        |&\verb|??>    }        |\\
\verb|??'    ^        |&\verb|??!    |        |&\verb|??-    ~        |
\end{tabular}
\end{center}

Никакие другие замены, кроме указанных, не делаются.

\begin{ApxComment}
Трёхзнаковые последовательности введены ANSI-стандартом.
\end{ApxComment}

\subsection{Склеивание строк}
\label{apx:subsec:concatenation_of_strings}

\index{склеивание строк}%
\index{define@\texttt{{\#}define}!в несколько строк}%
Строка, заканчивающаяся обратной наклонной чертой, соединяется со следующей,
поскольку литера \verb|\| и следующая за ней литера новая-строка выбрасываются.
Это делается перед <<разбиением>> текста на лексемы.

\subsection{Макроопределение и макрорасширение}
\label{apx:subsec:macro_definition_and_expansion}

\index{макрос!расширение}%
\index{определение!макроса}%
\index{препроцессор!макрос|(}%
\index{управляющая!строка|(}%
\index{define@\texttt{{\#}define}}%
Управляющая строка вида

\begin{ShortGramDecsWithCC}{\\\{\}}
# define \textit{идентификатор} \textit{последовательность-лексем}
\end{ShortGramDecsWithCC}
%
% в оригинале в левом нижнем углу страницы расположена надпись `` 8* ''
%

\noindent заставляет препроцессор заменять идентификатор на последовательность
лексем; пробельные литеры в начале и в конце последовательности лексем
выбрасываются. Повторная строка \verb|#define| с тем же идентификатором
считается ошибкой, если последовательности лексем неидентичны (несовпадения в
разделяющих пробельных литерах при сравнении во внимание не принимаются).

\index{макрос!с аргументами}%
\index{определение!макроса}%
\index{define@\texttt{{\#}define}}%
\index{define@\texttt{{\#}define}!с аргументами}%
Строка вида

{\setlength{\codeIndent}{0.25em}%
\begin{ShortGramDecsWithCC}{\\\{\}}
# define \textit{идентификатор}( \textit{список-идентификаторов} )\
\textit{последовательность-лексем}
\end{ShortGramDecsWithCC}
\setlength{\codeIndent}{\codeIndentBk}}


\noindent где между первым идентификатором и знаком \verb|(| не должно быть ни
одной пробельной литеры, представляет собой макроопределение с параметрами,
задаваемыми списком идентификаторов. Как и в первом варианте, пробельные литеры
в начале и в конце последовательности лексем выбрасываются, и макрос может быть
повторно определён только с тем же списком параметров и той же
последовательностью лексем.

\index{undef@\texttt{{\#}undef}}%
Управляющая строка вида

\begin{ShortGramDecsWithCC}{\\\{\}}
# undef \textit{идентификатор}
\end{ShortGramDecsWithCC}

\noindent предписывает препроцессору <<забыть>> определение, данное
идентификатору. Применение \verb|#undef| к неизвестному идентификатору ошибкой
не считается.

Если макроопределение было задано вторым способом, то текстуальная
последовательность, состоящая из его идентификатора с, возможно, следующими за
ним пробельными литерами, знака \verb|(|, списка лексем, разделённых занятыми, и
знака \verb|)|, представляет собой вызов макроса.
\index{лексема}%
Аргументами вызова макроса являются лексемы, разделённые запятыми (запятые,
<<закрытые>> кавычками или вложенными скобками, в разделении аргументов не
участвуют). Аргументы при их выделении макрорасширениям не подвергаются.
Количество аргументов в вызове макроса должно соответствовать количеству
параметров макроопределения. После выделения аргументов окружающие и пробельные
литеры выбрасываются. Затем в замещающей последовательности лексем макроса
идентификаторы-параметры (если они не окружены кавычками) заменяются на
соответствующие им аргументы. Если в замещающей последовательности перед
параметром не стоит знак \verb|#| и ни перед ним, ни после него нет знака
\verb|##|, то лексемы аргумента проверяются: не содержат ли они в себе
макровызова, и если это так, то прежде чем аргумент будет подставлен,
производится соответствующее ему макрорасширение.

\index{лексема!подстановка}%
\index{препроцессор!оператор \texttt{\#}}%
На процесс подстановки влияют два специальных оператора. Первый -- это оператор
\verb|#|, который ставится перед параметром. Он требует, чтобы подставляемый
вместо параметра и знака \verb|#| (перед ним) текст был заключён в двойные
кавычки. При этом в аргументе в стринговых литералах и литерных константах перед
каждой двойной кавычкой \verb|"| (включая и обрамляющие стринг), а также перед
каждой обратной наклонной чертой \verb|\| вставляется \verb|\|.

\index{конкатенация!лексем}%
\index{лексема!конкатенация}%
\index{препроцессор!оператор \texttt{\#\#}}%
Второй оператор записывается как \verb|##|. Если последовательность лексем в
любого вида макроопределении содержит оператор \verb|##|, то сразу после
подстановки параметров он вместе с окружающими его пробельными литерами
выбрасывается, благодаря чему <<склеиваются>> соседние лексемы, образуя тем
самым новую лексему. Результат не определён при получении неправильных лексем
или когда генерируемый текст зависит от порядка применения операторов \verb|##|.
Кроме того, \verb|##| не может стоять ни в начале, ни в конце замещающей
последовательности лексем.

В макросах обоих видов замещающая последовательность лексем повторно
просматривается на предмет обнаружения там новых \verb|define|-имён. Однако,
если некоторый идентификатор уже был заменён в данном расширении, повторное
появление такого идентификатора не вызовет его замены.

Если полученное расширение начинается со знака \verb|#|, оно не будет воспринято
как директива препроцессора.

\begin{ApxComment}
ANSI-стандарт описывает процесс макрорасширения более точно, чем первое издание.
Наиболее важные изменения касаются введения операторов \verb|#| и \verb|##|,
которые предоставляют возможность осуществлять расширения внутри стрингов и
конкатенацию лексем. Некоторые из новых правил, особенно касающиеся
конкатенации, могут показаться несколько странными. (См. приведённые ниже
примеры.)
\end{ApxComment}

Описанные возможности можно использовать для показа смысловой сущности констант,
как, например, в

\begin{ShortCodePar}
#define TABSIZE 100
int table[TABSIZE];
\end{ShortCodePar}

\noindent Определение

\begin{ShortCodePar}
#define ABSDIFF(a, b)   ((a)>(b) ? (a)-(b) : (b)-(a))
\end{ShortCodePar}

\noindent задаёт макрос, возвращающий абсолютное значение разности его
аргументов. В отличие от функции, делающей то же самое, аргументы и возвращаемое
значение здесь могут иметь любой арифметический тип и даже быть указателями.
Кроме того, аргументы, каждый из которых может иметь побочный эффект,
вычисляются дважды: один раз -- при проверке, другой раз -- при вычислении
результата.

Если имеется определение

\begin{ShortCodePar}
#define tempfile(dir)    #dir "/%s"
\end{ShortCodePar}

\noindent то макровызов \verb|tempfile(/usr/tmp)| даст в результате

\begin{ShortCodePar}
"/usr/tmp" "/%s"
\end{ShortCodePar}

\noindent Далее эти два стринга превратятся в один стринг. По макросу

\begin{ShortCodePar}
#define cat(x, y)    x ## y
\end{ShortCodePar}

\noindent вызов \verb|cat(var, 123)| сгенерирует \verb|var123|. Однако
\verb|cat(cat(1,2),3)| не даст желаемого, так как оператор \verb|##|
воспрепятствует получению правильных аргументов для внешнего вызова \verb|cat|.
В результате будет выдана следующая цепочка лексем:

\begin{ShortCodePar}
cat  (  1  ,  2  )3
\end{ShortCodePar}

\noindent где \verb|)3| (результат <<склеивания>> последней лексемы первого
аргумента с первой лексемой второго аргумента) не является правильной лексемой.
Если второй уровень макроопределения задан в виде

\begin{ShortCodePar}
#define xcat(x,y)    cat(x,y)
\end{ShortCodePar}

\noindent то никаких коллизий здесь не возникает; \verb|xcat(xcat(1,2),3)| в
итоге даст \verb|123|, поскольку сам \verb|xcat| не использует \verb|##|.

Аналогично сработает и \verb|ABSDIFF(ABSDIFF(a,b),c)|‚ и мы получим правильный
результат.

\subsection{Включение файла}
\label{apx:subsec:file_include}

\index{файл!включение}%
\index{include@\texttt{{\#}include}}%
Управляющая строка

\begin{ShortGramDecsWithCC}{\\\{\}}
# include <\textit{имя-файла}>
\end{ShortGramDecsWithCC}

\noindent заменяется на содержимое файла с именем \textit{имя-файла}. Среди
литер, составляющих \textit{имя-файла}, не должно быть знака \verb|>| и литеры
новая-строка. Результат не определён, если \textit{имя-файла} содержит любую из
литер \verb|"|, \verb|'|, \verb|\| или пару литер \verb|/*|. Порядок поиска
указанного файла зависит от реализации.

Подобным же образом выполняется управляющая строка

\begin{ShortGramDecsWithCC}{\\\{\}}
# include "\textit{имя-файла}"
\end{ShortGramDecsWithCC}

\noindent Сначала поиск осуществляется по тем же правилам, по каким компилятор
ищет первоначальный исходный файл (механизм этого поиска зависит от реализации),
а в случае неудачи осуществляется методом поиска, принятым в \verb|#include|
первого типа. Результат остаётся неопределённым, если имя файла содержит
\verb|'|, \verb|\| или \verb|/*|; использование знака \verb|>| разрешается.

Наконец, директива

\begin{ShortGramDecsWithCC}{\\\{\}}
# include \textit{последовательность-лексем}
\end{ShortGramDecsWithCC}

\noindent не совпадающая ни с одной из предыдущих форм, рассматривает
последовательность лексем как текст, который в результате всех макроподстановок
должен дать \verb|#include| с \verb|<...>| или с \verb|"..."|. Сгенерированная
таким образом директива далее будет интерпретироваться в соответствии с
полученной формой.

Файлы, вставляемые при помощи \verb|#include|, сами могут содержать в
себе директивы \verb|#include|.

\subsection{Условная компиляция}
\label{apx:subsec:conditional_compilation}

\index{условная компиляция}%
\index{elif@\texttt{{\#}elif}}%
\index{else a@\texttt{{\#}else}}%
\index{endif@\texttt{{\#}endif}}%
\index{if@\texttt{{\#}if}}%
\index{ifdef@\texttt{{\#}ifdef}}%
\index{ifndef@\texttt{{\#}ifndef}}%
Части программы могут компилироваться условно, если они оформлены в соответствии
со следующим схематично изображённым синтаксисом:

\begin{LongGramDecsWithCC}{\\\{\}}
\textit{условная-конструкция-препроцессора:}
     \textit{if-строка} \textit{текст} \textit{elif-части}\
\textit{else-часть\textsubscript{необ}} #endif

\textit{if-строка:}
     # if \textit{константное-выражение}
     # ifdef \textit{идентификатор}
     # ifndef \textit{идентификатор}

\textit{elif-части:}
     \textit{elif-строка} \textit{текст}
     \textit{elif-части\textsubscript{необ}}

\textit{elif-строка:}
     # elif \textit{константное-выражение}

\textit{else-часть:}
     \textit{else-строка} \textit{текст}

\textit{else-строка:}
     # else
\end{LongGramDecsWithCC}

\noindent Каждая из директив (\textit{if-строка}, \textit{elif-строка} и
\verb|#endif|) записывается на отдельной строке. Константные выражения в
\verb|#if| и последующих \verb|#elif|-строках вычисляются по порядку, пока не
обнаружится выражение с ненулевым значением; текст, следующий за строкой с
нулевым значением, выбрасывается. Текст, расположенный за директивой с ненулевым
значением, обрабатывается обычным образом. Под словом <<текст>> здесь имеется в
виду любая последовательность строк, включая строки препроцессора, которые не
являются частью условной структуры; текст может быть и пустым. Если \verb|#if|
или \verb|#elif|-строка с ненулевым значением выражения найдена и её текст
обработан, то последующие \verb|#elif| и \verb|#else|-строки вместе со своими
текстами выбрасываются. Если все выражения имеют нулевые значения и присутствует
строка \verb|#else|, то следующий за ней текст обрабатывается обычным образом.
Тексты <<неактивных>> ветвей условных конструкций, за исключением тех, которые
заведуют вложенностью условных конструкций, игнорируются.

\index{elif@\texttt{{\#}elif}}%
\index{if@\texttt{{\#}if}}%
Константные выражения в \verb|#if| и \verb|#elif| являются объектами для обычной
макроподстановки.
\index{препроцессор!оператор \texttt{defined}}%
\index{defined@\texttt{defined}}%
Более того, прежде чем просматривать выражения вида

\begin{ShortGramDecsWithCC}{\\\{\}}
defined \textit{идентификатор}
\end{ShortGramDecsWithCC}

\noindent и

\begin{ShortGramDecsWithCC}{\\\{\}}
defined ( \textit{идентификатор} )
\end{ShortGramDecsWithCC}

\noindent на предмет наличия в них макровызова, они заменяются на \verb|1L| или
\verb|0L| в зависимости от того, был или не был определён препроцессором
указанный в них идентификатор. Все идентификаторы, оставшиеся после
макрорасширения, заменяются на \verb|0L|. Наконец, предполагается, что любая
целая константа всегда имеет суффикс \verb|L|, т.е. вся арифметика имеет дело с
операндами только типа \verb|long| или \verb|unsigned long|.

Константное выражение~(\ref{apx:subsec:constant_expressions}) здесь используется
с ограничениями: оно должно быть целочисленным, не может содержать в себе
перечислимых констант, преобразований типа и операторов \verb|sizeof|.

\index{ifdef@\texttt{{\#}ifdef}}%
\index{ifndef@\texttt{{\#}ifndef}}%
Управляющие строки

\begin{ShortGramDecsWithCC}{\\\{\}}
#ifdef \textit{идентификатор}
#ifndef \textit{идентификатор}
\end{ShortGramDecsWithCC}

\noindent эквивалентны соответственно строкам

\begin{ShortGramDecsWithCC}{\\\{\}}
# if defined \textit{идентификатор}
# if ! defined \textit{идентификатор}
\end{ShortGramDecsWithCC}

\begin{ApxComment}
Строки \verb|#elif| не было в первой редакции, хотя она и использовалась в
некоторых препроцессорах. Оператор препроцессора \verb|defined| -- также новый.
\end{ApxComment}
\index{управляющая!строка|)}%
\index{препроцессор!макрос|)}%


\subsection{Нумерация строк}

\index{line@\texttt{{\#}line}}%
Для удобства работы с другими препроцессорами, генерирующими Си-программы, можно
использовать одну из следующих директив:

\begin{ShortGramDecsWithCC}{\\\{\}}
# line \textit{константа} "\textit{идентификатор}"
# line \textit{константа}
\end{ShortGramDecsWithCC}

\noindent которая предписывает компилятору <<считать>>, что указанные десятичное
целое и идентификатор являются номером следующей строки и именем текущего файла
соответственно. Если имя файла отсутствует, то ранее запомненное имя не
изменяется. Расширения макровызовов в \verb|line|-директиве выполняются до
интерпретации последней.

\subsection{Генерация сообщения об ошибке}

\index{error@\texttt{{\#}error}}%
Строка препроцессора вида

\begin{ShortGramDecsWithCC}{\\\{\}}
# error \textit{последовательность-лексем\textsubscript{необ}}
\end{ShortGramDecsWithCC}

\noindent приказывает ему выдать диагностическое сообщение, включающее заданную
последовательность лексем.

\subsection{Прагма}

\index{pragma@\texttt{{\#}pragma}}%
Управляющая строка вида

\begin{ShortGramDecsWithCC}{\\\{\}}
# pragma \textit{последовательность-лексем\textsubscript{необ}}
\end{ShortGramDecsWithCC}

\noindent призывает препроцессор выполнить зависящие от реализации действия.
Неопознанная прагма игнорируется.

\subsection{Пустая директива}

Строка препроцессора вида

\begin{ShortGramDecsWithCC}{\\\{\}}
#
\end{ShortGramDecsWithCC}

\noindent не вызывает никаких действий.

\subsection{Заранее определённые имена}
\label{apx:subsec:predefined_names}

\index{препроцессор!заранее определённые имена}%
Препроцессор <<понимает>> несколько заранее определённых идентификаторов; их он
заменяет специальной информацией.
\index{undef@\texttt{{\#}undef}}%
Эти идентификаторы (и оператор препроцессора \verb|defined| в том числе) нельзя
повторно переопределять, к ним нельзя также применять директиву \verb|#undef|.
Это следующие идентификаторы:

\begin{LongRtAlTab2cols}{0pt}{0pt}{\Verb|{\_}{\_}LINE{\_}{\_}|}
\verb|__LINE__|%
\index{препроцессор!заранее определённые имена!LINE@\texttt{\_\_LINE\_\_}}%
\index{LINE a (имя для препроцессора)@\texttt{\_\_LINE\_\_} (имя для препроцессора)}%
&Номер текущей строки исходного текста, десятичная константа.\\
\verb|__FILE__|%
\index{препроцессор!заранее определённые имена!FILE@\texttt{\_\_FILE\_\_}}%
\index{FILE (имя для препроцессора)@\texttt{\_\_FILE\_\_} (имя для препроцессора)}%
&Имя компилируемого файла, стринг.\\
\verb|__DATE__|%
\index{препроцессор!заранее определённые имена!DATE@\texttt{\_\_DATE\_\_}}%
&Дата компиляции в виде \verb|"Ммм дд гггг"|, стринг.\\
\verb|__TIME__|%
\index{препроцессор!заранее определённые имена!TIME@\texttt{\_\_TIME\_\_}}%
&Время компиляции в виде \verb|"чч:мм:сс"|‚ стринг.\\
\verb|__STDC__|%
\index{препроцессор!заранее определённые имена!STDC@\texttt{\_\_STDC\_\_}}%
&Константа $1$. Предполагается, что этот идентификатор определён как $1$ только
в тех реализациях, которые следуют стандарту.
\end{LongRtAlTab2cols}

\begin{ApxComment}
Строки \verb|#error| и \verb|#pragma| впервые введены ANSI-стандартом. Заранее
определённые макросы препроцессора также до сих пор не описывались, хотя и
использовались в некоторых реализациях.
\end{ApxComment}
\index{препроцессор|)}%
\index{макро-процессор|)}%


\section{Грамматика}
\label{apx:sec:grammar}

Ниже приведены сведённые воедино грамматические правила, описанные в данном
приложении. Они имеют то же содержание, но даны в ином порядке.

Здесь не приводятся определения следующих терминальных символов:
\textit{целая-константа}, \textit{литерная-константа},
\textit{с-плав-точкой-константа}, \textit{идентификатор}, \textit{стринг} и
\textit{перечислимая-константа}. Слова, набранные обычным латинским шрифтом, и
знаки рассматриваются как терминальные символы и используются буквально в том
виде, как записаны. Данную грамматику можно механически трансформировать в
текст, понятный системе автоматической генерации грамматического распознавателя.
Для этого помимо добавления некоторых синтаксических пометок, предназначенных
для указания альтернативных продукций, потребуется расшифровка конструкции со
словами <<один из>> и дублирование каждой продукции, использующей символ с
индексом \textit{необ}, причём один вариант продукции должен быть написан с этим
символом, а другой -- без него. С одним изменением, а именно удалением продукции
\textit{typedef-имя: идентификатор} и объявлением \textit{typedef-имя}
терминальным символом, данная грамматика будет понятна генератору
грамматического распознавателя YACC.
\index{неоднозначность \texttt{if-else}}%
\index{if-else@\texttt{if-else}!неоднозначность}%
Ей присуще лишь одно противоречие, вызываемое неоднозначностью
\verb|if|-\verb|else|-конструкции.

\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{компонента-трансляции:}
     \textit{внешняя-декларация}
     \textit{компонента-трансляции} \textit{внешняя-декларация}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{внешняя-декларация:}
     \textit{определение-функции}
     \textit{декларация}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{определение-функции:}
     \textit{спецификаторы-декларации\textsubscript{необ}} \textit{декларатор}
                    \textit{список-деклараций\textsubscript{необ}}\
\textit{составная-инструкция}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{декларация:}
     \textit{спецификаторы-декларации}\
\textit{список-иниц-деклараторов\textsubscript{необ}};
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{список-деклараций:}
     \textit{декларация}
     \textit{список-деклараций} \textit{декларация}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{спецификаторы-декларации:}
     \textit{спецификатор-класса-памяти}\
\textit{спецификаторы-декларации\textsubscript{необ}}
     \textit{спецификатор-типа}\
\textit{спецификаторы-декларации\textsubscript{необ}}
     \textit{квалификатор-типа}\
\textit{спецификаторы-декларации\textsubscript{необ}}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{спецификатор-класса-памяти:} один из
     auto    register    static    extern    typedef
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{спецификатор-типа:} один из
     void  char  short  int  long  float  double  signed  unsigned
        \textit{структ-или-объед-спецификатор}\
\textit{enum-спецификатор} \textit{typedef-имя}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{квалификатор-типа:} один из
     const    volatile
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{структ-или-объед-спецификатор:}
     \textit{структ-или-объед} \textit{идентификатор\textsubscript{необ}}\
\{ \textit{список-структ-деклараций} \}
     \textit{структ-или-объед} \textit{идентификатор}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{структ-или-объед:} один из
     struct    union
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{список-структ-деклараций:}
     \textit{структ-декларация}
     \textit{список-структ-деклараций} \textit{структ-декларация}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{список-иниц-деклараторов:}
     \textit{иниц-декларатор}
     \textit{список-иниц-деклараторов} , \textit{иниц-декларатор}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{иниц-декларатор:}
     \textit{декларатор}
     \textit{декларатор} = \textit{инициализатор}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{структ-декларация:}
     \textit{список-спецификаторов-квалификаторов}\
\textit{список-структ-деклараторов} ;
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{список-спецификаторов-квалификаторов:}
     \textit{спецификатор-типа}\
\textit{список-спецификаторов-квалификаторов\textsubscript{необ}}
     \textit{квалификатор-типа}\
\textit{список-спецификаторов-квалификаторов\textsubscript{необ}}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{список-структ-деклараторов:}
     \textit{структ-декларатор}
     \textit{список-структ-деклараторов} , \textit{структ-декларатор}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{структ-декларатор:}
     \textit{декларатор}
     \textit{декларатор\textsubscript{необ}} : \textit{константное-выражение}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{переч-спецификатор:}
     enum \textit{идентификатор\textsubscript{необ}}\
\{ \textit{список-перечислителей} \}
     enum \textit{идентификатор}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{список-перечислителей:}
     \textit{перечислитель}
     \textit{список-перечислителей} , \textit{перечислитель}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{перечислитель:}
     \textit{идентификатор}
     \textit{идентификатор} = \textit{константное-выражение}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{декларатор:}
     \textit{указатель\textsubscript{необ}} \textit{собственно-декларатор}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{собственно-декларатор:}
     \textit{идентификатор}
     ( \textit{декларатор} )
     \textit{собственно-декларатор}\
[ \textit{константное-выражение\textsubscript{необ}} ]
     \textit{собственно-декларатор} ( \textit{список-типов-параметров} )
     \textit{собственно-декларатор}\
( \textit{список-идентификаторов\textsubscript{необ}} )
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{указатель:}
     * \textit{список-квалификаторов-типа\textsubscript{необ}}
     * \textit{список-квалификаторов-типа\textsubscript{необ}}\
\textit{указатель}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{список-квалификаторов-типа:}
     \textit{квалификатор-типа}
     \textit{список-квалификаторов-типа} \textit{квалификатор-типа}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{список-типов-параметров:}
     \textit{список-параметров}
     \textit{список-параметров} , ...
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{список-параметров:}
     \textit{декларация-параметра}
     \textit{список-параметров} , \textit{декларация-параметра}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{декларация-параметра:}
     \textit{спецификаторы-декларации} \textit{декларатор}
     \textit{спецификаторы-декларации}\
\textit{абстрактный-декларатор\textsubscript{необ}}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{список-идентификаторов:}
     \textit{идентификатор}
     \textit{список-идентификаторов} , \textit{идентификатор}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{инициализатор:}
     \textit{выражение-присваивания}
     \{ \textit{список-инициализаторов} \}
     \{ \textit{список-инициализаторов} , \}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{список-инициализаторов:}
     \textit{инициализатор}
     \textit{список-инициализаторов} , \textit{инициализатор}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{имя-типа:}
     \textit{список-спецификаторов-квалификаторов}\
\textit{абстрактный-декларатор\textsubscript{необ}}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{абстрактный-декларатор:}
     \textit{указатель}
     \textit{указатель\textsubscript{необ}}\
\textit{собственно-абстрактный-декларатор}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{собственно-абстрактный-декларатор:}
     ( \textit{абстрактный-декларатор} )
     \textit{собственно-абстрактный-декларатор\textsubscript{необ}}\
[ \textit{константное-выражение\textsubscript{необ}} ]
     \textit{собственно-абстрактный-декларатор\textsubscript{необ}}\
( \textit{список-типов-параметров\textsubscript{необ}} )
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{typedef-имя:}
     \textit{идентификатор}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{инструкция:}
     \textit{помеченная-инструкция}
     \textit{инструкция-выражение}
     \textit{составная-инструкция}
     \textit{инструкция-выбора}
     \textit{циклическая-инструкция}
     \textit{инструкция-перехода}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{помеченная-инструкция:}
     \textit{идентификатор} : \textit{инструкция}
     case \textit{константное-выражение} : \textit{инструкция}
     default : \textit{инструкция}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{инструкция-выражение:}
     \textit{выражение\textsubscript{необ}} ;
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{составная-инструкция:}
     \{ \textit{список-декларации\textsubscript{необ}}\
\textit{список-инструкции\textsubscript{необ}} \}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{список-инструкций:}
     \textit{инструкция}
     \textit{список-инструкций} \textit{инструкция}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{инструкция-выбора:}
     if ( \textit{выражение} ) \textit{инструкция}
     if ( \textit{выражение} ) \textit{инструкция}\
else \textit{инструкция}
     switch ( \textit{выражение} ) \textit{инструкция}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{циклическая-инструкция:}
     while ( \textit{выражение} ) \textit{инструкция}
     do \textit{инструкция} while ( \textit{выражение} )
     for ( \textit{выражение\textsubscript{необ}} ;\
\textit{выражение\textsubscript{необ}} ;\
\textit{выражение\textsubscript{необ}} ) \textit{инструкция}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{инструкция-перехода:}
     goto \textit{идентификатор} ;
     continue ;
     break ;
     return \textit{выражение\textsubscript{необ}} ;
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{выражение:}
     \textit{выражение-присваивания}
     \textit{выражение} , \textit{выражение-присваивания}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{выражение-присваивания:}
     \textit{условное-выражение}
     \textit{унарное-выражение} \textit{оператор-присваивания}\
\textit{выражение-присваивания}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{оператор-присваивания:} один из
     =   *=   /=   %=   +=   -=   <<=   >>=   &=   ^=   |=
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{условное-выражение:}
     \textit{логическое-ИЛИ-выражение}
     \textit{логическое-ИЛИ-выражение} ?\
\textit{выражение} : \textit{условное-выражение}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{константное-выражение:}
     \textit{условное-выражение}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{логическое-ИЛИ-выражение:}
     \textit{логическое-И-выражение}
     \textit{логическое-ИЛИ-выражение} || \textit{логическое-И-выражение}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{логическое-И-выражение:}
     \textit{ИЛИ-выражение}
     \textit{логическое-И-выражение} && \textit{ИЛИ-выражение}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{ИЛИ-выражение:}
     \textit{исключающее-ИЛИ-выражение}
     \textit{ИЛИ-выражение} | \textit{исключающее-ИЛИ-выражение}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{исключающее-ИЛИ-выражение:}
     \textit{И-выражение}
     \textit{исключающее-ИЛИ-выражение} ^ \textit{И-выражение}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{И-выражение:}
     \textit{выражение-равенства}
     \textit{И-выражение} & \textit{выражение-равенства}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{выражение-равенства:}
     \textit{выражение-отношения}
     \textit{выражение-равенства} == \textit{выражение-отношения}
     \textit{выражение-равенства} != \textit{выражение-отношения}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{выражение-отношения:}
     \textit{сдвиговое-выражение}
     \textit{выражение-отношения} < \textit{сдвиговое-выражение}
     \textit{выражение-отношения} > \textit{сдвиговое-выражение}
     \textit{выражение-отношения} <= \textit{сдвиговое-выражение}
     \textit{выражение-отношения} >= \textit{сдвиговое-выражение}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{сдвиговое-выражение:}
     \textit{аддитивное-выражение}
     \textit{сдвиговое-выражение} >> \textit{аддитивное-выражение}
     \textit{сдвиговое-выражение} << \textit{аддитивное-выражение}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{аддитивное-выражение:}
     \textit{мультипликативное-выражение}
     \textit{аддитивное-выражение} + \textit{мультипликативное-выражение}
     \textit{аддитивное-выражение} - \textit{мультипликативное-выражение}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{мультипликативное-выражение:}
     \textit{выражение-приведённое-к-типу}
     \textit{мультипликативное-выражение} *\
\textit{выражение-приведённое-к-типу}
     \textit{мультипликативное-выражение} /\
\textit{выражение-приведённое-к-типу}
     \textit{мультипликативное-выражение} %\
\textit{выражение-приведённое-к-типу}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{выражение-приведённое-к-типу:}
     \textit{унарное-выражение}
     ( \textit{имя-типа} ) \textit{выражение-приведённое-к-типу}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{унарное-выражение:}
     \textit{постфиксное-выражение}
     ++ \textit{унарное-выражение}
     -- \textit{унарное-выражение}
     \textit{унарный-оператор} \textit{выражение-приведённое-к-типу}
     sizeof  \textit{унарное-выражение}
     sizeof  ( \textit{имя-типа} )
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{унарный-оператор:} один из
     &    *    +    -    ~    !
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{постфиксное-выражение:}
     \textit{первичное-выражение}
     \textit{постфиксное-выражение} [ \textit{выражение} ]
     \textit{постфиксное-выражение}\
( \textit{список-аргументов-выражений\textsubscript{необ}} )
     \textit{постфиксное-выражение} . \textit{идентификатор}
     \textit{постфиксное-выражение} -> \textit{идентификатор}
     \textit{постфиксное-выражение} ++
     \textit{постфиксное-выражение} --
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{первичное-выражение:}
     \textit{идентификатор}
     \textit{константа}
     \textit{стринг}
     ( \textit{выражение} )
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{список-аргументов-выражений:}
     \textit{выражение-присваивания}
     \textit{список-аргументов-выражений} , \textit{выражение-присваивания}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{константа:}
     \textit{целая-константа}
     \textit{литерная-константа}
     \textit{с-плав-точкой-константа}
     \textit{перечислимая-константа}
\end{ShortGramDecsWithCCFinBlock}

Грамматика языка препроцессора приводится в виде перечня структур управляющих
строк. Для механического получения программы грамматического разбора она не
годится. Грамматика включает символ \textit{текст}, который означает текст
обычной программы, неусловные управляющие строки препроцессора и его законченные
условные конструкции.

\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{управляющая-строка:}
     # define \textit{идентификатор} \textit{последовательность-лексем}
     # define \textit{идентификатор}( \textit{идентификатор} , ... ,\
\textit{идентификатор} )
                                                 \
\textit{последовательность-лексем}
     # undef \textit{идентификатор}
     # include <\textit{имя-файла}>
     # include "\textit{имя-файла}"
     # include \textit{последовательность-лексем}
     # line \textit{константа} "\textit{идентификатор}"
     # line \textit{константа}
     # error \textit{последовательность-лексем\textsubscript{необ}}
     # pragma \textit{последовательность-лексем\textsubscript{необ}}
     #
     \textit{условная-конструкция-препроцессора}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{условная-конструкция-препроцессора:}
     \textit{if-строка} \textit{текст} \textit{elif-части}\
\textit{else-часть\textsubscript{необ}} # endif
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{if-строка:}
     # if \textit{константное-выражение}
     # ifdef \textit{идентификатор}
     # ifndef \textit{идентификатор}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{elif-части:}
     \textit{elif-строка} \textit{текст}
     \textit{elif-части\textsubscript{необ}}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{elif-строка:}
     # elif \textit{константное-выражение}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{else-часть:}
     \textit{else-строка} \textit{текст}
\end{ShortGramDecsWithCCFinBlock}
\begin{ShortGramDecsWithCCFinBlock}{\\\{\}}
\textit{else-строка:}
     # else
\end{ShortGramDecsWithCCFinBlock}
%
% проверить форматирование слов в тексте приложения
% чтобы отсылки к грамматике были курсивом
%