先看一段奇葩代碼:
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、得知了第一點之後,我們應該注意在一條語句中,不要對一個變量進行多次的操作,因為你不知道編譯器,對這條語句將產生多少個中間變量,而引發血案~~