先看一段代碼:
#include<iostream>
using namespace std;
void func(int a, int b)
{
cout << a << " " << b << endl;
}
int main()
{
int a = 0;
func(a++, ++a);
return 0;
}
由于C++是從右向左入堆疊(與編譯器的呼叫約定有關,不是C++標準的規定),所以剛看到代碼的時候,我以為結果會是“1 1”(先將++a入堆疊,再將a++入堆疊),然而事實是:
,這是在VS上面運行的,在g++上也是一樣的結果,幸好VS還可以查看匯編代碼,
由于在VS上有十分方便的反匯編工具,所以接下來說的東西都基于VS2019自帶的反匯編,
設定斷點并除錯,便可以打開反匯編視窗:

下面這段就是在呼叫func函式時的匯編代碼:

mov eax,dword ptr [a]
add eax,1
mov dword ptr [a],eax //這三行指令將a+1
mov ecx,dword ptr [a]
mov dword ptr [ebp-0D0h],ecx //這兩行指令將a的值存盤到一個臨時地址(暫存器間接尋址)中
mov edx,dword ptr [a]
add edx,1
mov dword ptr [a],edx /這三行指令又將a+1
mov eax,dword ptr [a]
push eax //這兩行指令將a壓入堆疊
mov ecx,dword ptr [ebp-0D0h]
push ecx //這兩行指令將剛剛存盤的臨時地址的值壓入堆疊
call func (0A312E9h) //呼叫func函式
add esp,8 //esp為堆疊指標暫存器
如果將代碼改成
func(++a, ++a);
會是什么結果呢?答案是
mov eax,dword ptr [a]
add eax,1
mov dword ptr [a],eax //這三行指令將a+1
mov ecx,dword ptr [a]
add ecx,1
mov dword ptr [a],ecx //這三行指令將a+1
mov edx,dword ptr [a]
push edx //這兩行指令將a壓入堆疊
mov eax,dword ptr [a]
push eax //這兩行指令將a壓入堆疊
call func (09912E9h)
add esp,8
可以看到,將a++改成++a之后,指令少了將a的值保存起來的步驟,并且由于并非在讀取引數時就壓入堆疊,而是在所有引數的運算式執行完之后才壓入,所以最后壓入引數堆疊的都是最后的變數a,
那么結合匯編代碼就不難理解文章開頭為什么是“1 2”了,基本就是這樣的區別(注意:讀取引數和執行引數的運算式時也是從右往左的):

在呼叫函式的時候,引數要避免使用自增和自減,避免出現混亂,
文章為作者結合個人理解撰寫,可能會有錯漏的地方,如有錯誤,敬請指正,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/100187.html
標籤:C++
上一篇:c++指標全攻略
下一篇:長樂國慶集訓Day2
