Приоритет операции
Приоритет, ранг или старшинство операции или оператора — формальное свойство оператора/операции, влияющее на очередность его выполнения в выражении с несколькими различными операторами при отсутствии явного (с помощью скобок) указания на порядок их вычисления. Например, операцию умножения обычно наделяют бо́льшим приоритетом, чем операцию сложения, поэтому в выражении будет получено сначала произведение и , а потом уже сумма.
Операции могут иметь одинаковый приоритет, тогда они вычисляются по правилу ассоциативности, установленному для этих операций.
В формальных системах используется два способа задания приоритета любого оператора. Первый из них — распределение всех операторов по иерархии приоритетов. Этот способ всегда используется для задания приоритетов по умолчанию и фиксируется в описании языка в виде соглашения, что таким-то операторам присваивается такие-то приоритеты. Никакого отражения в синтаксисе языка он не получает, то есть при нём не используется никаких явных средств (= тех/иных символов) для указания приоритета операции.
Второй способ дает возможность менять приоритеты по умолчанию, указывая их в явном виде с помощью символов парных скобок. При этом глубина вложенности прямо пропорциональна величине приоритета, то есть более внутренние скобки указывают на больший приоритет, чем внешние, обрамляющие их. В предыдущем примере с суммой и произведением порядок вычисления можно поменять, используя скобки, записав всё выражение так: или же так: .
Практика ранжирования операций
В языке C++
Приоритет операций — очерёдность выполнения операций в выражении, при условии, что в выражении нет явного указания порядка следования выполнения операций (с помощью круглых скобок).
Если операции имеют одинаковый приоритет, то очерёдность выполнения таких операций определяется согласно свойству ассоциативности.
Ассоциативность — направление выполнения операций в случае, если операции имеют одинаковый приоритет:
| Приоритет | Операция | Ассоциативность | Описание |
|---|---|---|---|
| 1 | :: | слева направо | унарная операция разрешения области действия |
| [ ] | операция индексирования | ||
| () | круглые скобки | ||
| . | обращение к члену структуры или класса | ||
| -> | обращение к члену структуры или класса через указатель | ||
| 2 | ++ | слева направо | постфиксный инкремент |
| – – | постфиксный декремент | ||
| 3 | ++ | справа налево | префиксный инкремент |
| – – | префиксный декремент | ||
| 4 | * | слева направо | умножение |
| / | деление | ||
| % | остаток от деления | ||
| 5 | + | слева направо | сложение |
| — | вычитание | ||
| 6 | >> | слева направо | сдвиг вправо |
| << | сдвиг влево | ||
| 7 | < | слева направо | меньше |
| <= | меньше либо равно | ||
| > | больше | ||
| >= | больше либо равно | ||
| 8 | == | слева направо | равно |
| != | не равно | ||
| 9 | && | слева направо | логическое И |
| 10 | || | слева направо | логическое ИЛИ |
| 11 | ?: | справа налево | условная операция (тернарная операция) |
| 12 | = | справа налево | присваивание |
| *= | умножение с присваиванием | ||
| /= | деление с присваиванием | ||
| %= | остаток от деления с присваиванием | ||
| += | сложение с присваиванием | ||
| -= | вычитание с присваиванием | ||
| 13 | , | слева направо | запятая |
В сомнительных случаях следует использовать скобки. В некоторых случаях приоритет операций может давать неявные эффекты. Рассмотрим пример:
int n = 5;
cout << n += 3;
Несмотря на очевидность кода для человека, компилятор выдаст ошибку: в выражении в строке 2 первым выполнится оператор побитового сдвига (<<) так как его приоритет равен 6 и он выше чем приоритет оператора «сложение с присваиванием» (+=) 12. В итоге значение переменной n будет передано в поток cout, а операция += не выполнится.