b = (a) + (++a);
This has undefined behavior.
Quoting the C99 standard (actually the N1256 draft), 6.5p2:
Between the previous and next sequence point an object shall have its
stored value modified at most once by the evaluation of an expression.
Furthermore, the prior value shall be read only to determine the value
to be stored.
This expression both reads the value of a
and updates it, and the read operation (the LHS of the +
) is not used to determine the value to be stored by the write operation (the RHS of the +
).
The 2011 ISO C standard (quoting from the N1570 draft) states this differently, but with essentially the same meaning:
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.
(a)
is a value computation using the value of a
; (a++)
is a side effect on a
. Since the order of evaluation of the operands of +
is not specified, these two operations are unsequenced relative to each other.
So it's not just a matter of the order of evaluation being undefined -- the behavior is undefined, and is not limited to the possibilities of the operands of the +
operator being evaluated in either of the two possible orders.
And no, the parentheses don't change this.
Section 3 of the comp.lang.c FAQ explains this well.