2010-08-04 32 views
6

使用不同調用約定的關鍵因素是什麼?什麼時候有人知道在不同的場合使用特定的呼叫約定,如__cdecl__stdcall__fastcall何時使用調用約定

示例將被真正apprciated。

回答

12

大多數時候你不需要擔心它。通常你會使用__cdecl,但只是因爲這是Visual C++中的默認值。但是,C++成員函數在默認情況下使用Visual C++

當您將回調傳遞給API函數(如Windows API中的函數)時,您確實需要擔心調用約定的一種(相當常見的)情況:

// CALLBACK is #define'd as __stdcall 
LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg 
    WPARAM wParam, LPARAM lParam); 
// ... 
windowClass.lpfnWndProc = &MyWndProc; 
::RegisterClass(&windowClass); 

在這裏,我們聲明MyWndProc()作爲具有__stdcall約定(CALLBACK#define倒是如__stdcall)。這是因爲操作系統期望lpfnWndProc指向WNDPROC,which uses the CALLBACK convention

幾乎所有的Windows API,它接受一個回調函數需要回調函數使用__stdcall慣例,而且由於__cdecl通常是默認的,你必須更加明確,(你會使用CALLBACK的窗口過程)。

這非常重要,因爲如果操作系統嘗試調用非__stdcall函數,則可能會發生堆棧損壞。不幸的是,足夠的人得到這個錯誤Windows will actually check for calling convention mismatch specifically for window procedures

雖然__stdcall需要傳遞給WinAPI的函數回調函數,接受的參數個數可變必須使用__cdecl調用約定,因爲只有調用者將知道如何正確地彈出可變數量的參數從堆棧功能。由於__cdecl通常是默認值,因此您無需爲接受可變數量參數的函數明確指定__cdecl

我個人還沒有找到用於__fastcall,雖然我確定有人有。

__clrcall僅在您與託管代碼進行交互時纔有用。