函式的呼叫方與被呼叫方對於函式如何呼叫須要乙個明確的約定,這樣的約定就叫作呼叫慣例。
乙個呼叫慣例一般會規定如下幾方面的內容:
1. 函式引數的傳遞順序及方式
函式引數的傳遞有多種方式,常見的是通過棧傳遞。函式的呼叫方將引數壓入棧中,函式自己再從棧中取出引數。對於有多個引數的函式,呼叫慣例需要約定函式呼叫方將引數壓入棧的順序:是從左到右,還是從右到左。還有些呼叫慣例也支援使用暫存器來傳遞引數。
2. 棧的維護方式
在引數被壓入棧後,函式體被呼叫執行,此後需要將被壓入棧的引數再全部彈出,以使得棧在函式呼叫前後保持一致。這個彈出工作可以由呼叫方完成,也可以由被呼叫函式來完成。
3. 名字修飾的策略
為了鏈結的時候能夠對呼叫慣例進行區分,呼叫管理要對函式名進行修飾。不同的呼叫慣例也有不同的修飾策略。
下表列出幾個常見的呼叫慣例:
呼叫慣例
出棧方引數傳遞
名字修飾
cdecl
呼叫方從右至左的順序壓引數入棧
下劃線+函式名
stdcall
函式自身
從右至左的順序壓引數入棧
下劃線+函式名+@+引數的位元組數,如函式int func(int a, double b)的修飾名是_func@12
fastcall
函式自身
頭兩個dword(4位元組)型別或者佔更少位元組的引數被放入暫存器,其他剩下的引數按從右到左的順序入棧
@+函式名+@+引數的位元組數
pascal
函式自身
從左至右的順序入棧
較複雜,參見pascal 文件
其中cdecl 是c 語言預設的呼叫慣例。
此外,c 語言的諸如printf() 這樣支援可變引數的函式,也是依賴於cdecl 的從右向左傳遞引數從而得到實現的。
棧與呼叫慣例
每個程序分配的記憶體由很多部分組成,通常稱為 段 1.文字段 包含了程序執行的程式二進位制機器語言指令,唯讀,可共享,因為多個程序可同時執行同一程式 2.初始化資料段 包含顯式初始化的全域性變數和靜態變數 3.未初始化資料段 也稱為bss段,包含未進行顯示初始化的全域性變數和靜態變數。為什麼分開放呢...
呼叫約定呼叫慣例
呼叫約定是呼叫方和被呼叫方對於函式如何呼叫的乙個明確的約定,只有雙方都遵守同樣的約定函式才能被正確的呼叫。int foo int n,float m 如果函式的呼叫方在傳遞引數室先壓入引數n,再壓入引數m,而函式則認為呼叫方應該先先壓入引數m,再壓入引數n,那麼在內部中m與n的值將會被交換。再者,如...
VC 中的函式呼叫慣例
我們知道在進行函式呼叫時,有幾種呼叫方法,主要分為c式,pascal式.在c和c 中c式呼叫是預設的,類的成員函式預設呼叫為 stdcall。二者是有區別的,下面我們用例項說明一下 1.cdecl c和c 預設呼叫方式 例子 void input int m,int n 相當於void cdecl ...