先看一段奇葩代码:
int main(void) {
int x = 4;
int y;
y = (x++);
printf("hello world. y = %d.\n", y);
x = 4;
y = (x++)+(x++);
printf("hello world. y = %d.\n", y);
x = 4;
y = (x++)+(x++)+(x++);
printf("hello world. y = %d.\n", y);
x = 4;
y = (x++)+(x++)+(x++)+(x++);
printf("hello world. y = %d.\n", y);
x = 4;
y = (++x);
printf("hello world. y = %d.\n", y);
x = 4;
y = (++x)+(++x);
printf("hello world. y = %d.\n", y);
x = 4;
y = (++x)+(++x)+(++x);
printf("hello world. y = %d.\n", y);
x = 4;
y = (++x)+(++x)+(++x)+(++x);
printf("hello world. y = %d.\n", y);
return 0;
}
而在VS2012(windows运行环境)的测试结果为:
\\后++ y = 4. y = 8. //4+4 y = 12. //4+4+4 y = 16. //4+4+4+4 \\前++ y = 5. y = 12. //6+6 y = 21. //7+7+7 y = 32. //8+8+8+8
在Ubuntu上测试的结果为:
//后++ y = 4. y = 9. //4+5 y =15. //4+5+6 y = 22. //4+5+6+7 //前++ y = 5. y = 12. //6+6 y = 19. //6+6+7 y = 27. //6+6+7+8
对应windows上的测试结果都比较好理解:
1、对于后++而言,在赋值之前x不会递增,所以每次多一个x++不过是多一个4的累加而已。
2、对于前++而言,在赋值前x已经递增,所以每次多一个x所对应内存的值都被提高1,最后再相加。
所以出现了出现了6*2 7*3 8*4的结果。
对于linux上的测试结果就不太容易想明白:
1、对于后++而言第二就和windows的结果不一样了,这是因为linux用了产生中间变量的方式。
如:y = (x++)+(x++);被分成了多步:1)tmp = x; x = x + 1;2) tmp1 = x; x = x + 1; 3)y = tmp + tmp1;
1)中tem等于4,并递增了x;2)中tmp1就等4了也递增了x;3)中就等到结果4+5=9
当(x++)递增到三个时也是一样分析,只不过会多一个中间变量tmp2.
2、对于前++,第三个和windows的结果不同了,也是产生了中间变量的缘故:
如:y = (++x)+(++x)+(++x); 被分成了多步:
1)tmp = (++x)+(++x); 2)y = tmp + (++x);
从而y = 6+6+7
再如:y = (++x)+(++x)+(++x); 被分成了多步:
1)tmp = (++x)+(++x); 2)tmp1 = tmp + (++x); 3)y = tmp1 + (++x);
从而y = 6+6+7+8
这里可能唯一让人困惑的是为什么(++x)+(++x)中间没有产生中间变量?而(x++)+(x++)却产生了中间变量?
我猜想是因为前++应为是先递增后赋值,所以直接是x = x+1所以也就没有中间变量的产生,而作为最前面的
两个(++x)与‘+’作用产生一个表达式:(++x)+(++x),这个表达式赋值给一个中间变量在与后面的表达式依次作用。
总结:
1、对于vs的编译器,在一条语句中,没有产生多余的中间变量,而ubuntu中因为产生了中间的变量。
所以后++时ubuntu对x的内存空间有更多的操作,而前++时vs对x的内存空间有更多的操作。导致了结果的不一致。
2、得知了第一点之后,我们应该注意在一条语句中,不要对一个变量进行多次的操作,因为你不知道编译器,对这条语句将产生多少个中间变量,而引发血案~~