Variable a
is used as an lvalue twice in the expression.
Keep in mind that x ^= y
is in fact a shortcut for x = x ^ y
, and it means that the first operand is read, then written.
If you take the first operation out from the original expression, it is fine, see:
b ^= a ^= b; // OK
/* 2 1 */
Here, a
is used twice and b
is used three times. Since the assignment operator is right-to-left associative, first a ^= b
is calculated, variable b
is only read, variable a
is read and then written, and the result (r1) is passed to the second operation. On the second operation, b ^= r1
, b
is read a second time (giving the same value as read previously) and then written. Note there is no way to interpret differently, no undefined behavior. In the above statement, a
is read only once, b
is read twice but both reads return the same value, and both a
and b
is written only once. It is ok.
When you add the third assignment to the left, it becomes a problem:
a ^= b ^= a ^= b; // NOT OK
/* 3 2 1 */
Now, a
is read twice, once on operation 1 and once on operation 3, and also written on operation 1 and operation 3. What value should a
return on operation 3, the original value or the value after operation 1 is processed?
The clever programmer may think that operation 1 is completely executed before operation 3 is processed, but this is not defined by the standard. It just happens to work with most compilers. On operation 3, the compiler may very well return the same value for a
as it is returned for operation 1, causing the wrong result. This is undefined behavior.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…