c c 中入棧順序

2021-10-09 08:33:08 字數 2830 閱讀 5236

c/c++中的都是從右往左入棧的,在呼叫函式時,若引數需要運算則先運算,然**棧,再呼叫函式。

程式中棧頂在低位,棧低在高位。

程式入棧順序:

void

push

(int a,

int b,

int c)

先入棧的在棧底,應該儲存在高位;**棧的在棧頂,應該儲存在低位。

位置順序:c > b > a

所以:c最先入棧,a最**棧

函式呼叫是從右往左入棧的

函式引數有運算,則先計算完引數中的全部運算再執行函式

函式引數有運算需要區分是呼叫前執行還是呼叫後執行的函式(++i,i++)

入棧的是臨時變數還是實際變數

分析下面**的運算結果:

int

main()

也可從編譯後的彙編**中看出:

# printf("%d,%d\n", ++i, ++i);

# 取出i的值到暫存器

mov eax, dword ptr _i$[ebp]

# 暫存器自增1

add eax, 1

# 寫回到i

mov dword ptr _i$[ebp], eax

# 取出i的值到暫存器

mov ecx, dword ptr _i$[ebp]

# 暫存器自增1

add ecx, 1

# 寫回到i

mov dword ptr _i$[ebp], ecx

# 讀取i的值到寄存

mov edx, dword ptr _i$[ebp]

# 入棧

push edx

# 讀取i的值到寄存

mov eax, dword ptr _i$[ebp]

# 入棧

push eax

push offset $sg3750

# 呼叫_printf

call _printf

# printf("%d,%d\n", ++i, i++);

# 取出i的值

mov ecx, dword ptr _i$[ebp]

# 儲存到臨時變數

mov dword ptr tv71[ebp], ecx

# 取出i的值,並自增1,寫回i

mov edx, dword ptr _i$[ebp]

add edx, 1

mov dword ptr _i$[ebp], edx

# 取出臨時變數的值,併入棧

mov eax, dword ptr tv71[ebp]

push eax

mov ecx, dword ptr _i$[ebp]

push ecx

push offset $sg3751

call _printf

再思考一下下面的**執行結果:

#include

void

push

(int a,

int b,

int c)

intmain()

很多答案都提到是為了函式可以使用動態引數。

動態引數是如何實現的?

函式是通過棧傳入引數的,動態引數需要壓入個數和型別都未知的引數到棧中。而我們知道第乙個引數一定是最後乙個入棧的,在其他引數之上。

如何讀取動態引數?

引數肯定在棧裡,但是要如何讀取到棧中的引數呢?

熟悉彙編的可能會考慮通過esp暫存器,因為esp指向棧頂位置。但是在函式內,第乙個引數一定不是在棧頂位置:

如果沒有在函式最開始就獲取第乙個引數的位址,在程式執行中esp還可能會變,所以通過esp獲取乙個引數的位置是不可取的,而且不同的編譯器實現還不一定都一樣。

// 通過esp讀取引數值

void

push

(int a,

int b,

int c)

printf

("a = %d\r\n"

, i1)

;printf

("a = %d, ptr = 0x%x\r\n"

, a,

&a);

printf

("b = %d, ptr = 0x%x\r\n"

, b,

&b);

printf

("c = %d, ptr = 0x%x\r\n"

, c,

&c);

}

通過上面的分析,要實現動態引數,我們需要有乙個確切位址的引數,用來定位其他引數。所以在c++的實現中,帶有動態引數的函式,第乙個引數一定是個很明確的引數。

而且引數從右往左入棧,第乙個引數位置就非常明確,且可以快速定位第乙個引數的位置(esp+12)。

結論:引數從右往左入棧可以快速確定第乙個引數的位置,非常適合帶動態引數的函式

從左往右入參可以快速定位最後乙個引數的位置;但如果是動態引數,則無法定位最後乙個引數的位置(型別不確定,無法明確引數size)

動態引數的缺陷:

無法確定引數長度

無法確定引數型別

printf是通過格式化來確定輸出的引數長度和型別。

在寫dll時經常會用stdcall、cdecl宣告函式,為什麼要這樣?其實就是宣告函式引數的傳遞及銷毀方式。

他們之間的區別:

類的成員函式和非成員函式及普通函式在編譯後都是一樣的,類成員函式特殊的地方在於函式呼叫時會通過暫存器(ecx)傳遞this指標。

C C 語言函式中引數的入棧順序

對於函式,之前認為會用就行了,對其中的原理並不是很了解,就比如函式中引數的入棧順序 在這說明一下,函式的引數是儲存在棧中的,還有一些區域性變數也是存放在棧中 這個問題 於某網際網路的面試題,當然答得很不好,查了很多大牛的部落格做一下總結。include using namespace std voi...

合法入棧順序

題目描述 我們知道,乙個入棧序列是的合法出棧序列有,等,而是不合法的.現在冰語有乙個長度為n的序列a 保證序列內數字唯一,且1 a i n 他想知道這個序列是不是入棧順序的合法出棧序列,你能告訴他麼?輸入 第一行為t,表示樣例個數 每個樣例第一行為n,第二行為n個數 1 t 1e4,3 n 100 ...

出棧入棧順序問題

不定項選擇題 依次讀入資料元素序列入棧,每進乙個元素,機器可要求下乙個元素入棧或彈棧,如此進行,則棧空時彈出的元素構成的序列是以下 序列?牛客444334號 ada 可行步驟 a入棧,b入棧,c入棧,d入棧,d出棧,e入棧,e出棧,c出棧,f入棧,f出棧,b出棧,g入棧,g出棧,a出棧 b 不可行,...