Порядок выполнения операций
Порядок выполнения операций
Рассмотрим следующую строку:
butter = 25.0 + 60.0 * n / SCALE;
В этом операторе имеются операции сложения, умножения и деления. Какая операция будет выполнена первой? Будет ли 25.0 складываться с 60.0, затем результат 85.0 умножаться на n, а произведение делиться на значение константы SCALE? Или 60.0 умножается на n, результат складывается с 25.0, а сумма затем делится на величину SCALE? Или же существует какой-то другой порядок выполнения операций? Пусть переменная n равна 6.0, а константа SCALE - 2.0. Если вы выполните данные операции, используя эти значения, вы найдете, что при первом способе вычисления результат равен 255, а при втором - 192.5. При выполнении данной Си программы на машине реализуется, по-видимому, какой-то другой порядок вычислений, поскольку на деле переменная butter получит значение 205.0.
Совершенно очевидно, что изменение порядка выполнения действий может приводить к различным результатам, поэтому язык Си нуждается в наборе непротиворечивых правил, указывающих, какое действие осуществлять первым. Язык Си делает это, задавая приоритет той или иной операции. Каждой операции назначается уровень старшинства. Умножение и деление имеют более высокий уровень, чем сложение и вычитание, поэтому они выполняются первыми. Если же две операции имеют один и тот же уровень старшинства, они выполняются в том порядке, в котором присутствуют в операторе. Для большинства операций обычный порядок - слева направо. (Операция = является исключением из этого правила.) Поэтому в операторе
butter = 25.0 + 60.0 * n / SCALE;
порядок операций следующий:
60.0 * n - первое умножение (или, возможно, деление) (если n = 6, то 60.0 * n = 360.0).
360.0/SCALE - второе умножение (или, возможно, деление) и наконец (поскольку SCALE = 2.0):
25.0 + 180.0 - первое сложение (или, возможно, вычитание) дает 205.0.
Многие программисты предпочитают представлять порядок вычислений с помощью диаграммы специального вида, называемой "правом выражения". Ниже приводится пример такой диаграммы. Диаграмма показывает, как исходное выражение сводится к одному значению.
Если вы захотите, скажем, чтобы сложение выполнялось перед делением, тогда вы должны делать то же, что и мы в приведенной ниже строке:
hour = (25.0 + 60.0 * n) / SCALE;
В первую очередь выполняется все, что заключено в скобки; внутри действуют обычные правила. В данном примере сначала вы умножение, а затем сложение. С помощью этих действий вычисляется выражение в скобках, и только потом результат делится на значение константы SCALE.
Рис. 5.3. Деревья выражений, построенные на основе операции и операндов, и порядок вычислении.
Мы можем составить таблицу правил, касающихся уже использованных нами операции. (В приложении В в конце книги приведена таблица, где содержатся правила, относящиеся ко всем операциям языка Си.)
Таблица 5.1. Операции в порядке уменьшения уровня старшинства
ОПЕРАЦИИ ПОРЯДОК ВЫЧИСЛЕНИЯ ( ) слева направо -(унарный) слева направо * / слева направо + -(вычитание) слева направо = слева направоЗаметим, что два различных по смыслу употребления знака минус имеют разные приоритеты (уровни старшинства). Столбец "порядок вычисления" указывает, как операция связана со своими операндами. Например, унарный знак минус связан с величиной, стоящей справа от него, а при делении левый операнд делится на правый.
Попытаемся применить эти правила на более сложном примере
/* применение правил старшинства */
main( )
{
int top, score;
top = score = -(2 + 5)*6 + (4 + 3*(2 + 3));
printi("top = %d ", top);
}
Какое значение будет выведено на печать в результате работы данной программы? Вначале вычислите его сами, а затем выполните программу или прочитайте нижеследующее объяснение, чтобы проверить свой ответ. (Надеемся, что вы получите правильный результат.)
Итак, выражения, стоящие в скобках, имеют наивысший приоритет. Двигаясь слева направо, встречаем первое выражение скобках (2+5). Вычисляя его, получаем:
top = score = -7*6 + (4 + 3*(2 + 3))
Следущее выражение в скобках - это (4 + 3*(2 + 3)). Отбрасываем скобки, получаем 4 + 3*(2 + 3). Вот как! Еще одни скобки! Тогда первым шагом является нахождение суммы 2+3. Выражение примет вид:
top = score = -7*6 + (4 + 3*5)
Мы должны еще завершить вычисление выражения в скобках. По-скольку умножение * имеет приоритет более высокий, чем сложение, выражение теперь выглядит так
top = score = -7*6 + (4 + 15)
имеем
top = score = -7*6 + 19.
Что же дальше? Если вы предполагаете, что нужно найти произведение 7*6, то вы ошибаетесь. Заметим, что унарный минус (изменение знака) имеет более высокий приоритет, чем умножение *. Поэтому сначала число 7 заменяется на -7, а затем -7 умножается на 6. Строка примет вид:
top = score = -42 + 19
после этого в результате сложения получим
toр = score = -23
Затем переменной score присваивается значение -23, и, наконец, переменная top получает то же значение -23. Напомним, что операция = выполняется справа налево.