пятница, 21 ноября 2014 г.

Приоритет и очередность вычислений


В таблице 1 показаны приоритеты и очередность вычислений всех операторов. Операторы, перечисленные на одной строке, имеют одинаковый приоритет; строки упорядочены по убыванию приоритетов.

Таблица 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));

Обращения к функциям, вложенные присвоения, инкрементные и декрементные операторы дают "побочный эффект", проявляющийся в том, что при вычислении выражения значения некоторых переменных изменяются. В любом выражении с побочным эффектом может быть скрыта трудно просматриваемая зависимость результата выражения от очередности изменения значений переменных, входящих в выражение. В такой, например, типично неприятной ситуации

a[i] = i++;

возникает вопрос: массив a индексируется старым или измененным значением i?

Авторы книги рекомендуют не писать программы, зависящие от очередности вычислений, так как компиляторы могут по-разному их генерировать в зависимости от архитектуры машины.

Комментариев нет:

Отправить комментарий