前++和后++引发的血案~~!!

先看一段奇葩代码:

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、得知了第一点之后,我们应该注意在一条语句中,不要对一个变量进行多次的操作,因为你不知道编译器,对这条语句将产生多少个中间变量,而引发血案~~

posted @ 2016-05-14 09:43  宋桓公  阅读(1944)  评论(17编辑  收藏  举报