C Operator Precedence
В следующей таблице приведены приоритет и ассоциативность операторов C. Операторы перечислены сверху вниз в порядке убывания приоритета.
| Приоритет | Оператор | Описание | Ассоциативность |
|---|---|---|---|
| 1 |
++
--
|
Постфиксный инкремент и декремент | Слева направо |
()
|
Вызов функции | ||
[]
|
Индексация массива | ||
.
|
Доступ к члену структуры и объединения | ||
->
|
Доступ к члену структуры и объединения через указатель | ||
(
type
){
list
}
|
Составной литерал (C99) | ||
| 2 |
++
--
|
Префиксный инкремент и декремент [примечание 1] | Справа налево |
+
-
|
Унарный плюс и минус | ||
!
~
|
Логическое НЕ и побитовое НЕ | ||
(
type
)
|
Приведение типа | ||
*
|
Разыменование | ||
&
|
Взятие адреса | ||
sizeof
|
Размер [примечание 2] | ||
_Alignof
|
Требование выравнивания (C11) | ||
| 3 |
*
/
%
|
Умножение, деление и остаток от деления | Слева направо |
| 4 |
+
-
|
Сложение и вычитание | |
| 5 |
<<
>>
|
Побитовый сдвиг влево и вправо | |
| 6 |
<
<=
|
Для операторов отношения < и ≤ соответственно | |
>
>=
|
Для операторов отношения > и ≥ соответственно | ||
| 7 |
==
!=
|
Для операторов отношения = и ≠ соответственно | |
| 8 |
&
|
Побитовое И | |
| 9 |
^
|
Побитовое исключающее ИЛИ | |
| 10 |
|
|
Побитовое ИЛИ | |
| 11 |
&&
|
Логическое И | |
| 12 |
||
|
Логическое ИЛИ | |
| 13 |
?:
|
Тернарный условный оператор [примечание 3] | Справа налево |
| 14 [примечание 4] |
=
|
Простое присваивание | |
+=
-=
|
Присваивание с суммой и разностью | ||
*=
/=
%=
|
Присваивание с произведением, частным и остатком | ||
<<=
>>=
|
Присваивание с побитовым сдвигом влево и вправо | ||
&=
^=
|=
|
Присваивание с побитовым И, исключающим ИЛИ и ИЛИ | ||
| 15 |
,
|
Запятая | Слева направо |
-
↑
Операнд префиксных операторов
++и--не может быть приведением типа. Это правило грамматически запрещает некоторые выражения, которые в любом случае были бы семантически недопустимы. Некоторые компиляторы игнорируют это правило и обнаруживают недопустимость семантически. -
↑
Операнд оператора
sizeofне может быть приведением типа: выражение sizeof ( int ) * p однозначно интерпретируется как ( sizeof ( int ) ) * p , но не как sizeof ( ( int ) * p ) . -
↑
Выражение в середине условного оператора (между
?и:) разбирается так, как если бы оно было в скобках: его приоритет относительно?:игнорируется. - ↑ Левые операнды операторов присваивания должны быть унарными (неприведенными выражениями уровня 2). Это правило грамматически запрещает некоторые выражения, которые в любом случае были бы семантически недопустимы. Многие компиляторы игнорируют это правило и обнаруживают недопустимость семантически. Например, e = a < d ? a ++ : a = d — это выражение, которое не может быть разобрано из-за этого правила. Однако многие компиляторы игнорируют это правило и разбирают его как e = ( ( ( a < d ) ? ( a ++ ) : a ) = d ) , а затем выдают ошибку, поскольку оно семантически недопустимо.
При разборе выражения оператор, указанный в некоторой строке, будет связываться теснее (как если бы он был в скобках) со своими аргументами, чем любой оператор, указанный в строке ниже. Например, выражение * p ++ разбирается как * ( p ++ ) , а не как ( * p ) ++ .
Операторы, находящиеся в одной ячейке (в ячейке может быть перечислено несколько строк операторов), вычисляются с одинаковым приоритетом, в заданном направлении. Например, выражение a = b = c парсится как a = ( b = c ) , а не как ( a = b ) = c из-за правосторонней ассоциативности.
Примечания
Приоритет и ассоциативность независимы от порядка вычисления .
Сам стандарт не определяет уровни приоритета. Они выводятся из грамматики.
В C++ условный оператор имеет тот же приоритет, что и операторы присваивания, а префиксные
++
и
--
и операторы присваивания не имеют ограничений относительно своих операндов.
Спецификация ассоциативности избыточна для унарных операторов и приводится только для полноты: унарные префиксные операторы всегда ассоциируются справа налево ( sizeof ++* p это sizeof ( ++ ( * p ) ) ), а унарные постфиксные операторы всегда ассоциируются слева направо ( a [ 1 ] [ 2 ] ++ это ( ( a [ 1 ] ) [ 2 ] ) ++ ). Заметьте, что ассоциативность значима для операторов доступа к членам, даже несмотря на то, что они группируются с унарными постфиксными операторами: a. b ++ парсится как ( a. b ) ++ , а не как a. ( b ++ ) .
Ссылки
- Стандарт C17 (ISO/IEC 9899:2018):
-
- A.2.1 Выражения
- Стандарт C11 (ISO/IEC 9899:2011):
-
- A.2.1 Выражения
- Стандарт C99 (ISO/IEC 9899:1999):
-
- A.2.1 Выражения
- Стандарт C89/C90 (ISO/IEC 9899:1990):
-
- A.1.2.1 Выражения
Смотрите также
Порядок вычисления аргументов операторов во время выполнения.
| Общие операторы | ||||||
|---|---|---|---|---|---|---|
| присваивание |
инкремент
декремент |
арифметические | логические | сравнения |
доступа к членам
доступа |
другие |
|
a
=
b
|
++
a
|
+
a
|
!
a
|
a
==
b
|
a
[
b
]
|
a
(
...
)
|
|
C++ документация
для
приоритета операторов C++
|