不同編譯器產生的結果不同,本文測試環境為vs2013和vc6.
先看以下**:
int x = 3;
printf("%d%d%d%d%d%d", x, x++, x, ++x, x--, x);
vs2013輸出結果:434434
vc6輸出結果:444433
那麼問題來了:
(1)兩個編譯器printf的壓棧順序和計算順序是怎樣的?
(2)兩個編譯器如何對x++,++x處理的?
vs2013反彙編**
int x = 3;
010352ce mov dword ptr [x],3
printf("%d%d%d%d%d%d", x, x++, x, ++x, x--, x);
//x--
010352d5 mov eax,dword ptr [x]
010352d8 dword ptr [ebp-0d0h],eax //此時x = 3 ,將 x 的值存在 ebp-0d0h 這個相對位址中
010352de mov ecx,dword ptr [x]
010352e1 sub ecx,1
010352e4 mov dword ptr [x],ecx
printf("%d%d%d%d%d%d", x, x++, x, ++x, x--, x);
//++x 直接在edx完成
010352e7 mov edx,dword ptr [x]
010352ea add edx,1
010352ed mov dword ptr [x],edx //x = 3
//x++
010352f0 mov eax,dword ptr [x]
010352f3 mov dword ptr [ebp-0d4h],eax //此時x = 3 ,將 x 的值存在 ebp-0d4h 這個相對位址中
010352f9 mov ecx,dword ptr [x]
010352fc add ecx,1
010352ff mov dword ptr [x],ecx
//壓棧
01035302 mov esi,esp
01035304 mov edx,dword ptr [x]
01035307 push edx //4
01035308 mov eax,dword ptr [ebp-0d0h]
0103530e push eax //ebp-0d0h 位址中值為 3
0103530f mov ecx,dword ptr [x]
01035312 push ecx //4
01035313 mov edx,dword ptr [x]
01035316 push edx //4
01035317 mov eax,dword ptr [ebp-0d4h]
0103531d push eax //ebp-0d4h 位址中值為 3
0103531e mov ecx,dword ptr [x]
01035321 push ecx //4
01035322 push 103ca54h
01035327 call dword ptr ds:[1040184h]
結果 434434
vc6反彙編**
int x = 3
00401028 movd word ptr [ebp-4],3
printf("%d%d%d%d%d%d",x,x++,x,++x,x--,x);
0040102f mov eax,dword ptr [ebp-4]
00401032 push eax //x = 3
//x--
00401033 mov ecx,dword ptr [ebp-4]
00401036 mov dword ptr [ebp-8],ecx //ebp-8 值為3
00401039 mov edx,dword ptr [ebp-8]
0040103c push edx //x = 3
//++x 在eax完成
0040103d mov eax,dword ptr [ebp-4]
00401040 add eax,1
00401043 mov dword ptr [ebp-4],eax
00401046 mov ecx,dword ptr [ebp-4]
00401049 push ecx //x = 4
0040104a mov edx,dword ptr [ebp-4]
0040104d push edx //x = 4
//x++
0040104e mov eax,dword ptr [ebp-4]
00401051 mov dword ptr[ebp-0ch],eax //ebp-0ch 值為4
00401054 mov ecx,dword ptr[ebp-0ch]
00401057 push ecx //x = 4
00401058 mov edx,dword ptr [ebp-4]
0040105b push edx //x = 4
0040105c push offset string"%d%d%d%d%d%d" (0042201c)
00401061 mov eax,dword ptr [ebp-4] //操作的是x值
00401064 add eax,1
00401067 mov dword ptr [ebp-4],eax
0040106a mov ecx,dword ptr [ebp-4] //同上
0040106d sub ecx,1
00401070 mov dword ptr [ebp-4],ecx
00401073 call printf (004010b0)
結果 444433
由上反彙編**,我們可以得出以下結論:
(1)兩個編譯器的壓棧順序相同:從右到左
計算順序:
因編譯器而異,與壓棧順序無關。
(2)++x: 兩編譯器的處理方式相同,直接對暫存器進行值進行修改。
x++:vs2013將x值先儲存在某個相對位址中,再對現有x值累加計算,並繼續其他運算,最後將儲存的x值壓入棧中;vc6直接將x值壓入棧,並進行其他運算,壓棧完成以後再對x值進行累加計算。
總結:結果不同的原因是由於兩個編譯器對x++處理方式的不同,在比較x++和++x的實現方式時,我們發現x++會在實現中產生乙個副本,如果這個副本足夠大的時候,在一定程度上會影響計算的效率,應此++x應該優先使用。
以上只是個人觀點,有不合理之處歡迎各位指點。
C語言printf及引數壓棧順序
1.呼叫格式為 printf 格式化字串 參量表 其中格式化字串包括兩部分內容 一部分是正常字元,這些字元將按原樣輸出 另一部分是格式化規定字元,以 開始,後跟乙個或幾個規定字元,用來確定輸出內容格式。參量表是需要輸出的一系列引數,其個數必須與格式化字串所說明的輸出引數個數一樣多,各引數之間用 分開...
C語言 printf的執行順序
標籤 c語言 printf 執行順序 by 小威威 include int main void 輸出結果是30而不是31.首先,我們能夠肯定的是輸出的是第乙個引數,但是為什麼不是31呢?難道受到後面引數的影響?其實問題出在我們對printf的執行順序不了解。printf是從右往左執行的,即是prin...
C語言 printf函式執行順序
printf函式是從左往右讀取,然後將先讀取放到棧底,最後讀取的放在棧頂,處理時候是從棧頂開始的,所有我們看見的結果是,從右邊開始處理的。我們先看下這段 c語言經典面試題 include intmain int p arr p 100 printf d d n p p return0 輸出結果 13...