Namespaces
Variants

C Operator Precedence

From cppreference.net

В следующей таблице приведены приоритет и ассоциативность операторов 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 , Запятая Слева направо
  1. Операнд префиксных операторов ++ и -- не может быть приведением типа. Это правило грамматически запрещает некоторые выражения, которые в любом случае были бы семантически недопустимы. Некоторые компиляторы игнорируют это правило и обнаруживают недопустимость семантически.
  2. Операнд оператора sizeof не может быть приведением типа: выражение sizeof ( int ) * p однозначно интерпретируется как ( sizeof ( int ) ) * p , но не как sizeof ( ( int ) * p ) .
  3. Выражение в середине условного оператора (между ? и : ) разбирается так, как если бы оно было в скобках: его приоритет относительно ?: игнорируется.
  4. Левые операнды операторов присваивания должны быть унарными (неприведенными выражениями уровня 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 + = b
a - = b
a * = b
a / = b
a % = b
a & = b
a | = b
a ^ = b
a <<= b
a >>= b

++ a
-- a
a ++
a --

+ a
- a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

! a
a && b
a || b

a == b
a ! = b
a < b
a > b
a <= b
a >= b

a [ b ]
* a
& a
a - > b
a. b

a ( ... )
a, b
( type ) a
a ? b : c
sizeof


_Alignof
(начиная с C11)
(до C23)

alignof
(начиная с C23)

C++ документация для приоритета операторов C++