αλεχολυτ
αλεχολυτ

Reputation: 5039

Swap integers via XOR in single line. Is it really allowed in c++11?

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

Answers (1)

Columbo
Columbo

Reputation: 60979

The assignment operator (=) and the compound assignment operators all group right-to-left. [..]
The behavior of an expression of the form E1 op = E2 is equivalent to E1 = E1 op E2 except that E1 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

Related Questions