Таблица 1. Приоритеты и очередность вычислений операторов
Операторы | Выполняются | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
() | [] | -> | . | слева направо | |||||||
! | ~ | ++ | -- | + | - | * | & | (type) | sizeof | справа налево | |
* | / | % | слева направо | ||||||||
+ | - | слева направо | |||||||||
<< | >> | слева направо | |||||||||
< | <= | > | >= | слева направо | |||||||
== | != | слева направо | |||||||||
& | слева направо | ||||||||||
^ | слева направо | ||||||||||
| | слева направо | ||||||||||
&& | слева направо | ||||||||||
|| | слева направо | ||||||||||
?: | справа налево | ||||||||||
= | += | -= | *= | /= | %= | &= | ^= | |= | <<= | >>= | справа налево |
, | слева направо |
Примечание. Унарные операторы +, -, * и & имеют более высокий приоритет, чем те же бинарные операторы.
Приоритеты побитовых операторов &, ^ и | ниже, чем приоритет == и !=, из-за чего в побитовых проверках, таких как
if ((х & MASK) == 0) ...
чтобы получить правильный результат, необходимо использовать скобки.
чтобы получить правильный результат, необходимо использовать скобки.
В языке Си очередность вычисления операндов оператора не фиксируется. В инструкции
х = f() + g();
f может быть вычислена раньше g или наоборот. Из этого следует, что если одна из функций изменяет значение переменной, от которой зависит другая функция, то помещаемый в x результат может зависеть от очередности вычислений. Чтобы обеспечить нужную последовательность вычислений, промежуточные результаты можно запоминать во временных переменных.
printf("%d %d\n", ++n, power(2, n)); /* НЕВЕРНО */
может давать несовпадающие результаты. Результат вызова функции зависит от того, когда компилятор сгенерирует команды увеличения n — до или после обращения к power. Чтобы обезопасить себя от возможного побочного эффекта, достаточно написать
++n;
printf("%d %d\n", n, power(2, n));
printf("%d %d\n", n, power(2, n));
Обращения к функциям, вложенные присвоения, инкрементные и декрементные операторы дают "побочный эффект", проявляющийся в том, что при вычислении выражения значения некоторых переменных изменяются. В любом выражении с побочным эффектом может быть скрыта трудно просматриваемая зависимость результата выражения от очередности изменения значений переменных, входящих в выражение. В такой, например, типично неприятной ситуации
a[i] = i++;
возникает вопрос: массив a индексируется старым или измененным значением i?
Авторы книги рекомендуют не писать программы, зависящие от очередности вычислений, так как компиляторы могут по-разному их генерировать в зависимости от архитектуры машины.
Комментариев нет:
Отправить комментарий