Precedence establishes what operands are linked by what operators. It does not establish order of evaluation.
The assignment operator has very low precedence. As a result, without the parentheses, the expression
a = a + b - b = a
would be parsed as:
(a) = (a + b - b) = (a)
This would result in an error, because (a + b - b) is not an lvalue. So the parentheses are required in order to group the two operands b
and a
with the assignment operator, as in your original statement:
a = a + b - (b = a)
But all the parentheses impose is the grouping, not the order of evaluation.
All you can be sure of is that whenever (b = a)
is evaluated:
- the value of the entire expression will be the value of
a
- As a side effect,
b
will be assigned the value of a
.
When that will happen, however, is not predictable across compilers. The standard is explicit: in a complex expression, the order in which the subexpressions are evaluated and the order in which side-effects take place is unspecified, i.e., compiler dependent. The standard does not impose any requirements on the order in which subexpressions should be evaluated.
More generally, in C, if you modify a variable's value while using that variable elsewhere in the expression, the result you get will be undefined, which means anything could happen. You absolutely cannot rely on the expression a = a + b - (b = a)
, as it both modifies the value of b
and uses the value of b
elsewhere in the expression.
So the expression is evoking both unspecified behavior (relying on a specific order of evaluation) and undefined behavior (modifying a variable's value while using it elsewhere in the expression). Quite an impressive feat, when you think about it!
Edit: The above is true for C99. The latest standard, C11, explicitly calls this behavior undefined: "If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings." (6.5.2). The draft standard is available for free.