7

使用不同调用约定的关键因素是什么?什么时候有人知道在不同的场合使用特定的调用约定,例如__cdeclor__stdcall或 or 。__fastcall

例子真的很受欢迎。

4

1 回答 1

16

大多数时候你不需要担心它。通常您会使用__cdecl,但这只是因为这是 Visual C++ 中的默认设置。然而,C++ 成员函数__thiscall在 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约定(CALLBACKis #define'd as __stdcall)。这是必需的,因为操作系统期望lpfnWndProc指向 a WNDPROC它使用CALLBACK约定

几乎每个接受回调的 Windows API 函数都要求回调函数使用该__stdcall约定,并且由于__cdecl通常是默认设置,因此您必须明确说明(您将CALLBACK用于窗口过程)。

这一点非常重要,因为如果操作系统试图调用非__stdcall函数,就会发生堆栈损坏。不幸的是,很多人都犯了这个错误,以至于Windows 实际上会专门为窗口过程检查调用约定不匹配

虽然__stdcall传递给 WinAPI 函数的回调函数是必需的,但接受可变数量参数的函数必须使用__cdecl调用约定,因为只有调用者才知道如何正确地将可变数量的参数弹出堆栈。由于__cdecl通常是默认值,因此您不需要显式指定__cdecl接受可变数量参数的函数。

我个人还没有找到 的用途__fastcall,尽管我确信有人有。

__clrcall仅当您与托管代码交互时才相关。

于 2010-08-04T11:43:33.347 回答