C/C++函數調用約定

C/C++函數調用約定

關於 C/C++ 函數調用約定,大多數時候並不會影響程序邏輯,但遇到跨語言編程時,瞭解一下還是有好處的。

VC 中默認調用是 __cdecl 方式,Windows API 使用 __stdcall 調用方式,在 DLL 導出函數中,爲了跟 Windows API 保持一致,建議使用 __stdcall 方式。

調用約定跟堆棧清除密切相關。如果寫一個彙編函數,給 C/C++ 調用,在 __cdecl 方式下,則彙編函數無需清除堆棧,在 __stdcall 方式下,彙編函數需要在返回(RET)之前恢復堆棧。

C 語言有 __cdecl__stdcall__fastcallnaked__pascal

C++ 語言有 __cdecl__stdcall__fastcallnaked__pascal__thiscall,比 C 語言多出一種 __thiscall 調用方式。

 

    VC中,可以設置默認的調用約定,設置路徑爲:

Project à Properties à Configuration Properties à C/C++ à Advanced à Call Conversion

 

下面詳細介紹如上六種調用方式:

1__cdecl

__cdecl調用約定又稱爲 C 調用約定,是 C/C++ 語言缺省的調用約定。參數按照從右至左的方式入棧,函數本身不清理棧,此工作由調用者負責,返回值在EAX中。由於由調用者清理棧,所以允許可變參數函數存在,如int sprintf(char* buffer,const char* format,...);

 

2__stdcall

__stdcall 很多時候被稱爲 pascal 調用約定。pascal 語言是早期很常見的一種教學用計算機程序設計語言,其語法嚴謹。參數按照從右至左的方式入棧,函數自身清理堆棧,返回值在EAX中。

 

3__fastcall

顧名思義,__fastcall 的特點就是快,因爲它通過 CPU 寄存器來傳遞參數。他用 ECX EDX 傳送前兩個雙字(DWORD)或更小的參數,剩下的參數按照從右至左的方式入棧,函數自身清理堆棧,返回值在 EAX 中。

 

4naked

naked 是一個很少見的調用約定,一般不建議使用。編譯器不會給這種函數增加初始化和清理代碼,更特殊的是,你不能用return返回返回值,只能用插入彙編返回結果,此調用約定必須跟 __declspec 同時使用。例如定義一個求和程序,如__declspec(naked) int  add(int a,int b);

 

5__pascal

這是 pascal 語言的調用約定,跟 __stdcall 一樣,參數按照從右至左的方式入棧,函數自身清理堆棧,返回值在EAX中。VC 中已經廢棄了這種調用方式,因此在寫 VC 程序時,建議使用 __stdcall 代替。

 

6__thiscall

這是 C++ 語言特有的一種調用方式,用於類成員函數的調用約定。如果參數確定,this 指針存放於 ECX 寄存器,函數自身清理堆棧;如果參數不確定,this指針在所有參數入棧後再入棧,調用者清理棧。__thiscall 不是關鍵字,程序員不能使用。參數按照從右至左的方式入棧。

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