A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 左鹏辉2016 中级黑马   /  2016-3-27 23:35  /  1013 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

#define swap(a,b) a^=b^=a^=b
[cpp] view plain copy
#include <stdio.h>  
#define swap(a,b) a^=b^=a^=b  
int main(void)  
{  
    int a=1,b=2;  
    int c[]={1,2};  
    swap(a,b);  
    swap(c[0],c[1]);  
    printf("a=%d,b=%d\n",a,b);  
    printf("c[0]=%d,c[1]=%d\n",c[0],c[1]);  
    return 0;  
}  


在不同的编译器下得到的结果是不一样的:
在GCC下运行结果:
a=2,b=1
c[0]=0,c[1]=1
在VC6.0环境下运行结果:
a=2,b=1
c[0]=2,c[1]=1

原因是什么呢?

对于同一变量的两次修改不能放在一个表达式里,
因为C++语言没有在同一表达式中规定运算顺序,
所以在第二次更改同一变量时不能保证取到的结果是第一次修改之后的。

语言没有规定,那么行为就是未定义的。
没有定义,是指不同编译器会出现不一样的行为,同一编译器也会出现不一样的行为。顺序是由编译器自行决定的,它可能对这组数据采用这种顺序,对另一组数据采用另一种顺序。
不同编译器的实现不同,出现的结果也会不同。

具体解释如下:
a = 1 = 0001
b = 2 = 0010
a^=b^=a^=b; //对a修改了两次
先执行 a^=b   
a = 0011
再执行 b^=a
b = 0001
最后执行a^=b,即 a = a^b
这里的a不一定会取到第一次修改后的0011
也可能取到第一次修改之前的0001
如果取修改之后的,则 a=0011^0001 = 2;
如果取修改之前的,则 a=0001^0001 = 0;
所以gcc和vc编译器的结论有所不同。


3 个回复

倒序浏览
受教了,还有研究这个原理的,我们只讲了意思,没讲原理
回复 使用道具 举报
分析的很详细啊!
回复 使用道具 举报
z276698840 来自手机 中级黑马 2016-3-28 19:18:48
板凳
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马