C語言 printf計算順序和壓棧順序初探

2021-07-02 13:25:56 字數 3905 閱讀 7590

不同編譯器產生的結果不同,本文測試環境為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...