C 和 C++ 中关于“^=”运算符的区别

Difference between C and in C++ regarding the "^=" operator

我想使用表达式

交换 int *xint *y 指向的值
*x ^= *y ^= *x ^= *y;

(好吧,我知道这个表达很别扭,我只是想知道区别,没有冒犯。) 这在 C++ 中有效,但在 C 中失败。但是,如果我将它分成三个部分,如下所示

*x ^= *y;
*y ^= *x;
*x ^= *y;

它适用于两种语言。

那么,C和C++中的运算符^=有什么不同呢?

回答上述问题:C 和 C++ 之间的原始指针没有区别。

但我认为你真正的问题是别的...

在一条语句中多次修改同一个变量是未定义的行为,因此当您这样做时编译器可以做任何事情*x ^= *y ^= *x ^= *y。这与为什么 ++i + i++ 之类的总是错误的原因相同。

区别并不像您最初怀疑的那样在于指针,而在于求值规则的不同顺序。在 "new" C++11 "Sequenced-before rules" 中,我们有:

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)

(来自 cppr。)这条规则保证了你的表达式所需的从右到左的评估。

与此相反,C和C++98使用"Sequence points"。由于长语句中没有序列点,因此您对指针指向的值进行了多次未排序的修改,从而调用了未定义的行为。

对于 C,gcc 对此发出警告 (live)。对于 C++98,它显然已经使用了新规则,这很好,因为未定义的行为是未定义的。

拆分语句当然可以解决这个问题,因为语句的末尾明确地在您需要的地方引入了序列点。它也更优越,因为它更具可读性,并且不需要知道排序规则来确定代码是否正确。


供参考:可以找到 C++ 中顺序规则的精彩解释 here