Бьерн Страуструп - Язык программирования С++. Главы 2-4 - Порядок вычислений

ОГЛАВЛЕНИЕ

 

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

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

           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++). Оно

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