The rule does apply. f1
, f2
, and f3
may be evaluated in any order.
To expand a bit on some of the confusion (because people keep posting wrong answers), operator precedence does not affect the order in which things are evaluated. Take this example:
f1() * f2() + f3()
Now, we know that yes, the results of f1()
and f2()
are multiplied, and then added to the result of f3()
, but we don't know the order of evaluation. The parse tree looks like this:
+
/ \
* f3()
/ \
f1() f2()
But we don't know if the left side or the right side of +
will be evaluated first. It could be either way. Same with *
: we don't know if its left side or right side will be evaluated first.
The compiler could call f3()
, then store the result, then call f2()
, store that result, and then call f1()
, and then use the stored results to perform the actual computation.
Or, alternatively, it could call f1()
, store the result, then call f2()
, then use the two values to multiply (and then store that result), then call f3()
and finish the computation.
In each of these cases (or any other permutation of evaluation order), the functions were evaluated in different order, and yet the same answer is achieved.
To conclude: operator precedence determines the parse tree, not the order of evaluation. The order in which the parse tree is evaluated is unspecified.