Francis said:
OK, we have a problem linguistic problem here. Expressions are evaluated
and neither C nor C++ specify the order of evaluation of
sub-expressions. However both provide rules about how operators are
sequenced. The grammar largely specifies the order in which operators
are to be handled. For example
x = a*b*c/d;
allows any order for obtaining values from a, b, c and d but requires
that a*b be evaluated prior to the evaluation of that result * c which
must happen prior to the evaluation of that expression/d.
No, it does not require that.
It is worth noting that it is difficult to come to a definite answer in
this case, because we are taking about built-in operators and there's no
way to detect the order in which built-in operators are invoked by the
implementation. For this very reason I don't like the notion of "order
of evaluation" applied to built-in operators.
Grouping between operand and operators ultimately defines the _result_
of the expression, but not the order of evaluation of its
subexpressions. The implementation is free to choose absolutely any
method of evaluation that leads to the correct result. In the above case
the compiler is free to start with evaluating, say, 'b/d' if it knows
how to ensure that the final value in 'x' is correct.
It is worth noting that in many cases order of evaluation is tied to the
correctness of the result much more than it would be in abstract
mathematics (like in situations when intermediate subexpressions can
produce overflows, precision loss etc). In such cases evaluating the
expression in "canonical" order (defined by precedence and
associativity) is the most straightforward way to ensure that the result
is correct. But, once again, the compiler is not required to do it this way.
Where it get complicated is when we have for example:
y = (a+b) * (c+d);
Now either a+b or c+d can be evaluated first because there is no
ordering applied to multiple instances of expressions in parentheses.
This expression can also be evaluated as the sum of 'a*c', 'a*d', 'b*c'
and 'b*d', if the compiler chooses to so for some reason and is capable
of ensuring that the final result is correct.
Clear as mud to most people. Basically do not write code where the order
in which the sub-expressions are evaluated makes any difference to the
result.
Yes, as long as there are no side effects. Side effect make things much
more complicated. I've seen people, who'd erroneously apply the above
rule and come to the conclusion that the following expression is OK,
because it "doesn't depend on the order of evaluation":
const int a[] = { 1, 2, 3 };
const int* p = a;
int sum = *p++ + *p++ + *p++; // <- this one