C/C++函數(shù)調(diào)用約定
關(guān)于 C/C++ 函數(shù)調(diào)用約定,大多數(shù)時候并不會影響程序邏輯,但遇到跨語言編程時,了解一下還是有好處的。
VC 中默認調(diào)用是 __cdecl 方式,Windows API 使用 __stdcall 調(diào)用方式,在 DLL 導(dǎo)出函數(shù)中,為了跟 Windows API 保持一致,建議使用 __stdcall 方式。
調(diào)用約定跟堆棧清除密切相關(guān)。如果寫一個匯編函數(shù),給 C/C++ 調(diào)用,在 __cdecl 方式下,則匯編函數(shù)無需清除堆棧,在 __stdcall 方式下,匯編函數(shù)需要在返回(RET)之前恢復(fù)堆棧。
C 語言有 __cdecl、__stdcall、__fastcall、naked、__pascal。
C++ 語言有 __cdecl、__stdcall、__fastcall、naked、__pascal、__thiscall,比 C 語言多出一種 __thiscall 調(diào)用方式。
在VC中,可以設(shè)置默認的調(diào)用約定,設(shè)置路徑為:
Project à Properties à Configuration Properties à C/C++ à Advanced à Call Conversion。
下面詳細介紹如上六種調(diào)用方式:
1、__cdecl
__cdecl調(diào)用約定又稱為 C 調(diào)用約定,是 C/C++ 語言缺省的調(diào)用約定。參數(shù)按照從右至左的方式入棧,函數(shù)本身不清理棧,此工作由調(diào)用者負責(zé),返回值在EAX中。由于由調(diào)用者清理棧,所以允許可變參數(shù)函數(shù)存在,如int sprintf(char* buffer,const char* format,...);。
2、__stdcall
__stdcall 很多時候被稱為 pascal 調(diào)用約定。pascal 語言是早期很常見的一種教學(xué)用計算機程序設(shè)計語言,其語法嚴謹。參數(shù)按照從右至左的方式入棧,函數(shù)自身清理堆棧,返回值在EAX中。
3、__fastcall
顧名思義,__fastcall 的特點就是快,因為它通過 CPU 寄存器來傳遞參數(shù)。他用 ECX 和 EDX 傳送前兩個雙字(DWORD)或更小的參數(shù),剩下的參數(shù)按照從右至左的方式入棧,函數(shù)自身清理堆棧,返回值在 EAX 中。
4、naked
naked 是一個很少見的調(diào)用約定,一般不建議使用。編譯器不會給這種函數(shù)增加初始化和清理代碼,更特殊的是,你不能用return返回返回值,只能用插入?yún)R編返回結(jié)果,此調(diào)用約定必須跟 __declspec 同時使用。例如定義一個求和程序,如__declspec(naked) int add(int a,int b);。
5、__pascal
這是 pascal 語言的調(diào)用約定,跟 __stdcall 一樣,參數(shù)按照從右至左的方式入棧,函數(shù)自身清理堆棧,返回值在EAX中。VC 中已經(jīng)廢棄了這種調(diào)用方式,因此在寫 VC 程序時,建議使用 __stdcall 代替。
6、__thiscall
這是 C++ 語言特有的一種調(diào)用方式,用于類成員函數(shù)的調(diào)用約定。如果參數(shù)確定,this 指針存放于 ECX 寄存器,函數(shù)自身清理堆棧;如果參數(shù)不確定,this指針在所有參數(shù)入棧后再入棧,調(diào)用者清理棧。__thiscall 不是關(guān)鍵字,程序員不能使用。參數(shù)按照從右至左的方式入棧。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點擊舉報。