为什么与整数进行异或交换会触发警告?
我输入了以下程序:
#include <stdio.h>
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
默认会实现按位异或。
非常感谢。
I typed the following program:
#include <stdio.h>
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;
}
and it's ok. When I try to compile it, I get this:
$ 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
That's pretty much standard code, isn't it?
Why does it trigger a warning? As far as I know, bitwise XOR is implemented by default for int
as long as you are using a standard implementation of C.
Thank you very much.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
变量
a
在表达式中两次用作左值。请记住,
x ^= y
实际上是x = x ^ y
的快捷方式,这意味着先读取第一个操作数,然后再写入。如果你把第一个操作从原来的表达式中取出来,就可以了,参见:
这里,
a
使用了两次,b
使用了三次。由于赋值运算符是从右到左关联的,因此首先计算a ^= b
,变量b
仅被读取,变量a
为读取然后写入,结果 (r1) 传递给第二个操作。在第二次操作中,b ^= r1
,b
被第二次读取(给出与先前读取的值相同的值),然后写入。请注意,没有办法进行不同的解释,没有未定义的行为。在上面的语句中,a
仅读取一次,b
读取两次,但两次读取返回相同的值,并且a
和>b
仅写入一次。没关系。当您在左侧添加第三个赋值时,就会出现问题:
现在,
a
被读取两次,一次在操作 1 上,一次在操作 3 上,并且还在操作 1 和操作 3 上写入。操作 3 中应该返回值,原始值还是操作 1 处理后的值?聪明的程序员可能会认为操作1在操作3处理完之前就已经完全执行了,但这并不是标准定义的。它恰好适用于大多数编译器。在操作 3 中,编译器很可能为
a
返回与操作 1 返回的值相同的值,从而导致错误的结果。这是未定义的行为。Variable
a
is used as an lvalue twice in the expression.Keep in mind that
x ^= y
is in fact a shortcut forx = x ^ y
, and it means that the first operand is read, then written.If you take the first operation out from the original expression, it is fine, see:
Here,
a
is used twice andb
is used three times. Since the assignment operator is right-to-left associative, firsta ^= b
is calculated, variableb
is only read, variablea
is read and then written, and the result (r1) is passed to the second operation. On the second operation,b ^= r1
,b
is read a second time (giving the same value as read previously) and then written. Note there is no way to interpret differently, no undefined behavior. In the above statement,a
is read only once,b
is read twice but both reads return the same value, and botha
andb
is written only once. It is ok.When you add the third assignment to the left, it becomes a problem:
Now,
a
is read twice, once on operation 1 and once on operation 3, and also written on operation 1 and operation 3. What value shoulda
return on operation 3, the original value or the value after operation 1 is processed?The clever programmer may think that operation 1 is completely executed before operation 3 is processed, but this is not defined by the standard. It just happens to work with most compilers. On operation 3, the compiler may very well return the same value for
a
as it is returned for operation 1, causing the wrong result. This is undefined behavior.a ^= b ^= a ^= b;
调用 未定义行为< /a>.你应该使用这个:a ^= b ^= a ^= b;
invokes Undefined Behaviour. You should use this: