Namespaces
Variants

Приоритет операторов C

С ru.cppreference.net
 
 
 
 

В следующей таблице приведены приоритет и ассоциативность операторов 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 , Запятая Слева направо
  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++).

Ссылки

  • Стандарт 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 Выражения

Смотрите также

Порядок вычисления аргументов оператора во время выполнения.

Распространённые операторы
присваивание инкремент
декремент
арифметические логические сравнения доступ к
членам
прочие

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++