Reputation: 5039
I still could not clearly understand whether the expression x ^= y ^= x ^= y;
valid in C++11 (as they say in this thread) or it leads to undefined behavior?
The reasons given by the link seem convincing, but clang throws a warning:
warning: unsequenced modification and access to 'x' [-Wunsequenced]
Moreover, if both versions:
x ^= y ^= x ^= y; // (1)
x = x ^ (y = y ^ (x = (x ^ y))); // (2)
considered equivalent (and well-defined in C++11), why it gives different results (first, second)?
Additionally, it should be noted that the gcc gives a warning about sequence point only on the second version of code.
Upvotes: 6
Views: 523
Reputation: 60979
The assignment operator (=) and the compound assignment operators all group right-to-left. [..]
The behavior of an expression of the formE1 op = E2
is equivalent toE1 = E1 op E2
except thatE1
is evaluated only once.
Thus your code is equivalent to
x = x ^ (y ^= (x ^= y)));
... with x evaluated only once in x = x ...
.
Unfortunately, for xor's, the evaluation of the operands is unsequenced. I.e.
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.
applies. But now we have a problem:
x = x ^ (y ^= (x ^= y)));
// * ******
// | |
// | Side effect
// Value computation
The value computation (which is implied in the singular evaluation of x
for the two leftmost x
) and the side effect are unsequenced wrt each other, hence we induce UB:
If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.
Upvotes: 11