为什么XOR与整数交换会触发警告?

我输入了以下程序:

#include  int main(void) { int a = 3; int b = 42; printf("a = %d\nb = %d\n", a, b); printf("Exchanging values.\n"); a ^= b ^= a ^= b; printf("a = %d\nb = %d\n", a, b); return 0; } 

没关系。 当我尝试编译它时,我得到了这个:

 $ gcc test.c -o test -Wall -Wextra -ansi -pedantic-errors test.c: In function 'main': test.c:11: warning: operation on 'a' may be undefined 

这几乎是标准代码,不是吗?

为什么会触发警告? 据我所知,只要您使用C的标准实现,就会默认为int实现按位XOR。

非常感谢你。

变量a在表达式中用作左值两次。

请记住, x ^= y实际上是x = x ^ y的快捷方式,这意味着读取第一个操作数,然后写入。

如果你从原始表达式中取出第一个操作,那很好,请参阅:

  b ^= a ^= b; // OK /* 2 1 */ 

这里, a使用两次, b使用三次。 由于赋值运算符是从右到左的关联,首先计算a ^= b ,仅读取变量b ,读取变量a然后写入,并将结果( r1 )传递给第二个操作。 在第二个操作中,第二次读取b ^= r1b (给出与先前读取的值相同的值),然后写入。 请注意,没有办法以不同的方式解释,没有未定义的行为。 在上面的语句中, a只读取一次, b读取两次但两次读取都返回相同的值, ab只写入一次。 没关系。

当你向左添加第三个赋值时,它就成了一个问题:

  a ^= b ^= a ^= b; // NOT OK /* 3 2 1 */ 

现在, a被读取两次,一次是在操作1上,一次是在操作3上,也是在操作1和操作3上写入的。操作3,原始值或操作1之后的值应该返回什么值?

聪明的程序员可能认为操作1在处理操作3之前完全执行,但这不是由标准定义的。 它恰好适用于大多数编译器。 在操作3中,编译器可以很好地返回与为操作1返回的a相同的值,从而导致错误的结果。 这是未定义的行为。

a ^= b ^= a ^= b; 调用未定义的行为 。 你应该用这个:

 a ^= b; b ^= a; a ^= b;