I want to exchange the values pointed to by int *x
and by int *y
using the expression
*x ^= *y ^= *x ^= *y;
(Well,I know this expression is awkward, and I just want to know the difference, no offense.) This worked in C++, but failed in C. However if I divide it into three parts, like below
*x ^= *y;
*y ^= *x;
*x ^= *y;
It works fine for both languages.
So, what are the difference of the operator ^=
in C and C++?
The difference is not in the pointers as you initially suspected, but in the different order of evaluation rules. In the "new" C++11 "Sequenced-before rules", we have:
The side effect (modification of the left argument) of the built-in assignment operator and of all built-in compound assignment operators is sequenced after the value computation (but not the side effects) of both left and right arguments, and is sequenced before the value computation of the assignment expression (that is, before returning the reference to the modified object)
(From cppr.) This rule guarantees the desired right-to-left evaluation of your expression.
In contrast to this, C and C++98 use "Sequence points". Since there are no sequence points in the long statement, you have multiple unsequenced modification of the values the pointers point to and thus invoke Undefined Behavior.
For C, gcc warns about this (live). For C++98 it apparently uses the new rules already, which is fine because undefined behavior is undefined.
Splitting the statement solves this problem of course because the end of the statement explicitly introduces sequence points where you need them. It is also superior because it is more readable and one does not need to know sequencing rules to determine whether or not the code is correct.
For reference: A great explanation of sequencing rules in C++ can be found here.