Язык программирования C++ от Страуструпа

Порядок вычислений


Порядок вычисления подвыражений, входящих в выражение, не всегда определен. Например:

int i = 1;

v[i] = i++;

Здесь выражение может вычисляться или как v[1]=1, или как v[2]=1. Если нет ограничений на порядок вычисления подвыражений, то транслятор получает возможность создавать более оптимальный код. Транслятору следовало бы предупреждать о двусмысленных выражениях, но к сожалению большинство из них не делает этого. Для операций

&&    ||   ,

гарантируется, что их левый операнд вычисляется раньше правого операнда. Например, в выражении b=(a=2,a+1) b присвоится значение 3. Пример операции || был дан в $$3.2.1, а пример операции && есть в $$3.3.1. Отметим, что операция запятая отличается по смыслу от той запятой, которая используется для разделения параметров при вызове функций. Пусть есть выражения:

f1(v[i],i++);       // два параметра

f2( (v[i],i++) )    // один параметр

Вызов функции f1 происходит с двумя параметрами: v[i] и i++, но порядок вычисления выражений параметров неопределен. Зависимость вычисления значений фактических параметров от порядка вычислений - далеко не лучший стиль программирования. К тому же программа становится непереносимой. Вызов f2 происходит с одним параметром, являющимся выражением, содержащим операцию запятая:  (v[i], i++). Оно эквивалентно i++.

Скобки могут принудительно задать порядок вычисления. Например, a*(b/c) может вычисляться как (a*b)/c (если только пользователь видит в этом какое-то различие). Заметим, что для значений с плавающей точкой результаты вычисления выражений a*(b/c) и (a*b)/ могут различаться весьма значительно.



Содержание раздела