函數調用規約(__stdcall 和 __cdecl 的區別淺析)

CPU中,計算機沒有辦法知道一個函數調用需要多少個、什麼樣的參數,也沒有硬件可以保存這些參數。也就是說,計算機不知道怎麼給這個函數傳遞參數,傳遞參數的工作必須由函數調用者和函數本身來協調。爲此,計算機提供了一種被稱爲棧的數據結構來支持參數傳遞。

在參數傳遞中,有兩個很重要的問題必須得到明確說明:

當參數個數多於一個時,按照什麼順序把參數壓入堆棧函數調用後,由誰來把堆棧恢復原裝。在高級語言中,通過函數調用約定來說明這兩個問題。常見的調用約定有:stdcallcdeclfastcallthiscallnaked call

 

stdcall調用約定:
stdcall很多時候被稱爲pascal調用約定,因爲pascal是早期很常見的一種教學用計算機程序設計語言,其語法嚴謹,使用的函數調用約定就是stdcall。在Microsoft C++系列的C/C++編譯器中,常常用PASCAL宏來聲明這個調用約定,類似的宏還有WINAPICALLBACK
stdcall調用約定聲明的語法爲(以前文的那個函數爲例):
int __stdcall function(int a,int b)
stdcall的調用約定意味着:1)參數從右向左壓入堆棧,2)函數自身修改堆棧 3)函數名自動加前導的下劃線,後面緊跟一個@符號,其後緊跟着參數的尺寸。

注意不同編譯器會插入自己的彙編代碼以提供編譯的通用性,但是大體代碼如此。

 

cdecl調用約定:
cdecl調用約定又稱爲C調用約定,是C語言缺省的調用約定,它的定義語法是:
int function (int a ,int b) //不加修飾就是C調用約定
int __cdecl function(int a,int b)//明確指出C調用約定
cdecl調用約定的參數壓棧順序是和stdcall是一樣的,參數首先由有向左壓入堆棧。所不同的是,函數本身不清理堆棧,調用者負責清理堆棧。

 

_stdcall _cdecl是兩種不同的函數調用約定,區別在函數參數入棧的順序,由調用函數還是被調用函數將參數彈出棧,以及產生函數修飾名的方法。對於參數可變的函數如printf,使用的是_cdecl調用約定,Win32API函數都遵循_stdcall調用約定。在VC++開發環境中,默認的編譯選項是_cdecl,對於那些需要_stdcall調用約定的函數,必須顯式的加上_stdcall.


__stdcall 和 __cdecl 的區別淺析

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章