Which of the following options can achieve a swapping effect for pair
(*, *)
? Note that ^ represents XOR operation. For binary numbers, 0 XOR 0 = 0, 0 XOR 1 = 1, 1 XOR 0 = 1, 1 XOR 1 = 0.A.
(x, y): x ^= y ^= x ^= y;
B.
(a[x], a[y]): a[x] ^= a[y] ^= a[x] ^= a[y];
C.
(x, y): x -= y += x -= y;
D.
(a[x], a[y]): a[x] -= a[y] += a[x] -= a[y];
I've seen that C and D are not logically correct. And A is correct I guess. But I'm not sure what's the difference between A and B?
Don't forget that the equal operations are interpreted from right to left.
Case A:
x ^= y ^= x ^= y;
// is equivalent to : x ^= ( y ^= ( x ^= y ) );
// I use indice for each successive value of x and y, x0 and y0 are initial values
// x1 = x0 ^ y0
// y1 = y0 ^ x1 = y0 ^ (x0 ^ y0),
// because ^ operator is associative and commutative, and because X^X is 0
// y1 = x0, final value of y is initial value of x
// x2 = x1 ^ y1 = (x0 ^ y0) ^ (x0) = y0 final value of x is initial value of y
If x and y are integer variables of same type, the code is valid and swaps x and y
Case B:
It is pretty much the same as A, x
and y
are not modified and are indices in an array. If a[]
elements are integers, it is valid and swaps 2 items of the array a
only if x
and y
are different!
If x
and y
are identical, in a[x] ^= a[y]
, a[x]
and a[y]
are the same l-value, and it is erased losing its initial value.
Case C:
x -= y += x -= y; // equivalent: x -= ( y += ( x -= y ) );
// x1 = x0 - y0
// y1 = y0 + (x0-y0) = x0
// x2 = x1 - y1 = (x0-y0) - (x0) = -y0, final value of x is the opposite of initial value of y
// to swap value of x and y, we must take the opposite of last x
y += x -= y, x = y - x; // this does swap x and y
Case D:
Same as case C, but applies to elements of a[]
and also has issue if x
and y
are identical.
Note:
The equal operator is totally sequenced since C11.
The standard stipulates for assignment (6.5.16)
The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands.