Приоритет операторов C
В следующей таблице приведены приоритет и ассоциативность операторов C. Операторы перечислены сверху вниз в порядке убывания приоритета.
| Приоритет | Оператор | Описание | Ассоциативность |
|---|---|---|---|
| 1 | ++ --
|
Суффиксный/постфиксный инкремент и декремент | Слева направо |
()
|
Вызов функции | ||
[]
|
Индексация массива | ||
.
|
Доступ к члену структуры или объединения | ||
->
|
Доступ к члену структуры или объединения через указатель | ||
(type){list}
|
Составной литерал(C99) | ||
| 2 | ++ --
|
Префиксный инкремент и декремент[1] | Справа налево |
+ -
|
Унарный плюс и минус | ||
! ~
|
Логическое НЕ и побитовое НЕ | ||
(type)
|
Приведение | ||
*
|
Разыменование (разыменование указателя) | ||
&
|
Взятие адреса | ||
sizeof
|
Определение размера[2] | ||
_Alignof
|
Требование выравнивания(C11) | ||
| 3 | * / %
|
Умножение, деление и остаток | Слева направо |
| 4 | + -
|
Сложение и вычитание | |
| 5 | << >>
|
Побитовый сдвиг влево и вправо | |
| 6 | < <=
|
Для операторов отношения < и ≤ соответственно | |
> >=
|
Для операторов отношения > и ≥ соответственно | ||
| 7 | == !=
|
Для операторов отношения = и ≠ соответственно | |
| 8 | &
|
Побитовое И | |
| 9 | ^
|
Побитовое исключающее ИЛИ (XOR) | |
| 10 | |
|
Побитовое включающее ИЛИ (OR) | |
| 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++).
Ссылки
- Стандарт C23 (ISO/IEC 9899:2024):
- A.3.1 Выражения
- Стандарт 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 Выражения
Смотрите также
Порядок вычисления аргументов оператора во время выполнения.
| Распространённые операторы | ||||||
|---|---|---|---|---|---|---|
| присваивание | инкремент декремент |
арифметические | логические | сравнения | доступ к членам |
прочие |
|
|
|
|
|
|
|
|
Документация C++ по приоритету операторов C++
|