Язык программирования Си. Издание 3-е, исправленное - Брайан Керниган
Шрифт:
Интервал:
Закладка:
A7.13. Оператор побитового ИЛИ
ИЛИ выражение:
исключающее-ИЛИ-выражение
ИЛИ-выражение | исключающее-ИЛИ-выражение
Выполняются обычные арифметические преобразования; результат - побитовое OR операндов. Оператор применяется только к целочисленным операндам.
A7.14. Оператор логического И
логическое-И-выражение:
ИЛИ-выражение
логическое-И-выражение && ИЛИ-выражение
Операторы && выполняются слева направо. Оператор && выдает 1, если оба операнда не равны нулю, и 0 в противном случае. В отличие от &, && гарантирует, что вычисления будут проводиться слева направо: вычисляется первый операнд со всеми побочными эффектами; если он равен 0, то значение выражения есть 0. В противном случае вычисляется правый операнд, и, если он ранен 0, то значение выражения есть 0, в противном случае оно равно 1.
Операнды могут принадлежать к разным типам, но при этом каждый из них должен иметь либо арифметический тип, либо быть указателем. Тип результата - int.
A7.15. Оператор логического ИЛИ
логическое-ИЛИ-выражение:
логическое-И-выражение
логическое-ИЛИ-выражение || логическое-И-выражение
Операторы || выполняются слева направо. Оператор || выдает 1, если по крайней мере один из операндов не равен нулю, и 0 в противном случае. В отличие от |, оператор || гарантирует, что вычисления будут проводиться слева направо: вычисляется первый операнд, включая все побочные эффекты; если он не равен 0, то значение выражения есть 1. В противном случае вычисляется правый операнд, и если он не равен 0, то значение выражения есть 1, в противном случае оно равно 0.
Операнды могут принадлежать разным типам, но операнд должен иметь либо арифметический тип, либо быть указателем. Тип результата - int.
А7.16. Условный оператор
условное-выражение:
логическое-ИЛИ-выражение
логическое-ИЛИ-выражение ? выражение : условное-выражение
Вычисляется первое выражение, включая все побочные эффекты; если оно не равно 0, то результат есть значение второго выражения, в противном случае - значение третьего выражения. Вычисляется только один из двух последних операндов: второй или третий. Если второй и третий операнды арифметические, то выполняются обычные арифметические преобразования, приводящие к некоторому общему типу, который и будет типом результата. Если оба операнда имеют тип void, или являются структурами или объединениями одного и того же типа, или представляют собой указатели на объекты одного и того же типа, то результат будет иметь тот же тип, что и операнды. Если один из операндов имеет тип "указатель", а другой является константой 0, то 0 приводится к типу "указатель", этот же тип будет иметь и результат. Если один операнд является указателем на void, а второй - указателем другого типа, то последний преобразуется в указатель на void, который и будет типом результата.
При сравнении типов указателей квалификаторы типов (A8.2) объектов, на которые указатели ссылаются, во внимание не принимаются, но тип результата наследует квалификаторы обеих ветвей условного выражения
A7.17. Выражения присваивания
Существует несколько операторов присваивания; они выполняются справа налево.
выражение-присваивания:
условное-выражение
унарное-выражение оператор-присваивания выражение-присваивания
оператор-присваивания: один из
=
*=
/=
%=
+=
-=
<<=
>>=
&=
^=
|=
Операторы присваивания в качестве левого операнда требуют lvalue, причем модифицируемого; это значит, что оно не может быть массивом, или иметь незавершенный тип, или быть функцией. Тип левого операнда, кроме того, не может иметь квалификатора const; и, если он является структурой или объединением, в них не должно быть элементов или подэлементов (для вложенных структур или объединений) с квалификаторами const.
Тип выражения присваивания соответствует типу его левого операнда, а значение равно значению его левого операнда после завершения присваивания.
В простом присваивании с оператором = значение выражения замещает объект, к которому обращается lvalue. При этом должно выполняться одно из следующих условий: оба операнда имеют арифметический тип (если типы операндов разные, правый операнд приводится к типу левого операнда); оба операнда есть структуры или объединения одного и того же типа; один операнд есть указатель, а другой - указатель на void; левый операнд - указатель, а правый - константное выражение со значением 0; оба операнда - указатели на функции или объекты, имеющие одинаковый тип (за исключением возможного отсутствия const или volatile у правого операнда).
Выражение E1 op= E2 эквивалентно выражению E1 = E1 op(E2) с одним исключением: E1 вычисляется только один раз.
A7.18. Оператор запятая
выражение:
выражение-присваивания
выражение , выражение-присваивания
Два выражения, разделенные запятой, вычисляются слева направо, и значение левого выражения отбрасывается. Тип и значение результата совпадают с типом и значением правого операнда. Вычисление всех побочных эффектов левого операнда завершается перед началом вычисления правого операнда. В контексте, в котором запятая имеет специальное значение, например в списках аргументов функций (A7.3.2) или в списках инициализаторов (A8.7) (здесь в качестве синтаксических единиц фигурируют выражения присваивания), оператор запятая может появиться только в группирующих скобках. Например, в
f(a, (t=3, t+2), c)
три аргумента, из которых второй имеет значение 5.
A7.19. Константные выражения
Синтаксически, константное выражение - это выражение с ограниченным подмножеством операторов:
константное-выражение:
условное-выражение
При указании case-меток в переключателе, задании границ массивов и длин полей битов, на месте значений перечислимых констант и инициализаторов, а также в некоторых выражениях для препроцессора требуются выражения, вычисление которых приводит к константе.
Константные выражения не могут содержать присваиваний, операторов инкрементирования и декрементирования, вызовов функций и операторов-запятых; перечисленные ограничения не распространяются на операнд оператора sizeof. Если требуется получить целочисленное константное выражение, то его операнды должны состоять из целых, перечислимых (enum), символьных констант и констант с плавающей точкой; операции приведения должны специфицировать целочисленный тип, а любая константа с плавающей точкой - приводиться к целому. Из этого следует, что в константном выражении не может быть массивов, операций косвенного обращения (раскрытия указателя), получения адреса и доступа к полям структуры. (Однако для sizeof возможны операнды любого вида.)
Для константных выражений в инициализаторах допускается большая свобода; операндами могут быть константы любого типа, а к внешним или статическим объектам и внешним и статическим массивам, индексируемым константными выражениями, возможно применять унарный оператор &. Унарный оператор & может также неявно присутствовать при использовании массива без индекса или функции без списка аргументов. Вычисление инициализатора должно давать константу или адрес ранее объявленного внешнего или статического объекта плюс-минус константа.
Меньшая свобода допускается для целочисленных константных выражений, используемых после #if: не разрешаются sizeof-выражения, константы типа enum и операции приведения типа. (см. A12.5.)
A8. Объявления
То, каким образом интерпретируется каждый идентификатор, специфицируется объявлениями; они не всегда резервируют память для описываемых ими идентификаторов. Объявления, резервирующие память, называются определениями и имеют следующий вид: