什么方式定義的函數可以直接調用?
1. CALLBACK,WINAPI和AFXAPI到底是什么?它們分別在什么地方被定義的?
在頭文件windef.h中,CALLBACK, WINAPI, APIENTRY
……
#define CALLBACK __stdcall
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY WINAPI
……
在頭文件AFXVER_.H中,AFXAPI的定義如下:
……
// AFXAPI is used on global public functions
#ifndef AFXAPI
#define AFXAPI __stdcall
#endif
……
2. __stdcall和__cdecl有什么作用?他們的區別是什么?
a. __stdcall是新標準C/C++函數的調用方法。從底層上說,使用這種調用方法參數的進棧順序和標準C調用(__cdecl方法)是一樣的,都
是從右到左,但是__stdcall采用自動清棧的方式,而__cdecl是手工清棧。
b. windows規定,凡事由它來負責調用的函數必須定義為_stdcall類型,比如回調函數、WinMain函數等。
c. 如果沒有顯試聲明的話,函數的調用方法默認是__cdecl。
3. 調用約定種類
一共有5中函數調用約定(calling convention),它決定一下內容:
1) 函數參數的壓棧順序
2) 由調用者還是被調用者把參數彈出棧
3) 產生函數修飾名的方法
__stdcall調用約定:
函數的參數自右向左通過棧傳遞,被調用的函數在返回前清理傳送參數的內存棧,
__cdecl調用約定:
是C和C++程序的缺省調用方式。每一個調用它的函數都包含清空堆棧的代碼,所以產生的可執行文件大小會比調用__stdcall函數的大。函數采用從右到左的壓棧方式。注意:對于可變參數的成員函數,始終使用__cdecl的轉換方式。
__fastcall調用約定:
它是通過寄存器來傳送參數的(實際上,它用ECX和EDX傳送前兩個雙字(DWORD)或更小的參數,剩下的參數仍舊自右向左壓棧傳送,被調用的函數在返回前清理傳送參數的內存棧)。
thiscall調用約定:
僅僅應用于"C++"成員函數。this指針存放于CX寄存器,參數從右到左壓。thiscall不是關鍵詞,因此不能被程序員指定。
naked call調用約定:
采用上述4種調用約定時,如果必要的話,進入函數時編譯器會產生代碼來保存ESI,EDI,EBX,EBP寄存器,退出函數時則產生代碼恢復這些寄存器的內容。naked call不產生這樣的代碼。naked call不是類型修飾符,故必須和_declspec共同使用。