歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C/C++函數調用約定

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

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

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

C 語言有 __cdecl、__stdcall、__fastcall、naked、__pascal。

C++ 語言有 __cdecl、__stdcall、__fastcall、naked、__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 中。

 

4、naked

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 不是關鍵字,程序員不能使用。參數按照從右至左的方式入棧。

Copyright © Linux教程網 All Rights Reserved