如何评估涉及多个^ =运算符的表达式?

时间:2015-05-26 12:12:47

标签: c

#include<stdio.h>
 int main(){

     int arr[ 5 ] = { 1, 2, 3, 4, 5 };

     int *f = arr;

     int *l = (4+arr);

     while(f<l){

       *f^=*l^=*f^=*l; 

       ++f; --l;  
}

printf("\n%d\t%d\t%d\n", *arr, *f, *l)

return 0;

}

我的输出是1 3 3在纸上,但编译器显示033。 请有人向我解释。 提前谢谢。

3 个答案:

答案 0 :(得分:4)

*f^=*l^=*f^=*l; 

^=的操作数的评估未按顺序排列,并且您在同一表达式中多次使用相同的变量,两者之间没有序列点。

这意味着程序的行为未定义。没有人能够知道如何评估表达式,任何事情都可能发生。程序可能崩溃或输出可能是任何东西。

您必须通过将代码更改为此来修复此错误:

*f ^= *l;
*l ^= *f;
*f ^= *l;

然后每个分号将引入一个序列点,并且没有评估问题的顺序。

Standard references.

答案 1 :(得分:1)

我实际上并不关心如何评估它。如果你有代码并询问“这段代码究竟做了什么”,那么正确的答案是“不要编写那种代码”。 (除非你正在编写一个编译器,在这种情况下答案是“你不应该编写编译器,如果你要求堆栈溢出如何执行某些代码”)。

此外,结果是在C ++ C ++之前的C,C ++和Objective-C中的未定义行为,因此这是在定义它的地方不这样做的一个很好的理由。此外,它没有机会通过任何代码审查,并且有一条规则“总是假设下一个维护程序员阅读你的代码是一个知道你家庭地址的暴力反社会人士”。

答案 2 :(得分:0)

输出正确:

*arr = ((1^5)^1)^5);

确实是0。请注意,*arr在第一次迭代期间被修改,这就是您所担心的。在第二次和以后的迭代中,您不再修改*arr。此时f已更新,不再指向arr

解释数学的几行:

  1. 1^5 = 4
  2. 4^1 = 5
  3. 5^5 = 0
  4. 修改

    我认为语言保证评估顺序是从左到右。正如Lundin所指出的那样情况并非如此。但是,通过可执行文件的输出来判断,这很可能是编译器处理它的方式。