Приоритет операторов C
В следующей таблице перечислены приоритет и ассоциативность операторов 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++).
Ссылки
- Стандарт 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++ |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/c/language/operator_precedence