何时使用调用约定
使用不同调用约定的关键因素是什么?什么时候有人知道在不同场合使用特定的调用约定,例如__cdecl
或__stdcall
或__fastcall
。
例子将非常感激。
What are the key factors on using different calling conventions? When does someone know to use specific calling conventions such as __cdecl
or __stdcall
or __fastcall
in different occasions.
Examples would be really apprciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
大多数时候你不需要担心它。通常您会使用
__cdecl
,但这只是因为这是 Visual C++ 中的默认设置。然而,C++ 成员函数在 Visual C++ 中默认使用 __thiscall 约定 在一种(相当常见)的情况下,您真正需要担心调用约定的情况是,当您将回调传递给 API 函数时,例如Windows API:
在这里,我们将
MyWndProc()
声明为具有__stdcall
约定(CALLBACK
是#define
'd如__stdcall
)。这是必需的,因为操作系统期望lpfnWndProc
指向WNDPROC
,使用CALLBACK
约定。几乎每个接受回调的 Windows API 函数都要求回调函数使用
__stdcall
约定,并且由于__cdecl
通常是默认值,因此您必须明确说明这一点(您将对窗口过程使用CALLBACK
)。这非常重要,因为如果操作系统尝试调用非
__stdcall
函数,则可能会发生堆栈损坏。不幸的是,很多人都犯了这个错误,Windows 实际上会专门检查调用约定是否不匹配窗口过程。虽然传递给 WinAPI 函数的回调函数需要 __stdcall,但接受可变数量参数的函数必须使用 __cdecl 调用约定,因为只有调用者知道如何正确调用将可变数量的参数从堆栈中弹出。由于
__cdecl
通常是默认值,因此您无需为接受可变数量参数的函数显式指定__cdecl
。我个人还没有发现
__fastcall
的用途,尽管我确信有人已经找到了。仅当您与托管代码交互时,
__clrcall
才相关。Most of the time you don't need to worry about it. Usually you'll use
__cdecl
, but only because that's the default in Visual C++. C++ member functions, however, use the__thiscall
convention by default in Visual C++A (rather common) situation where you really have to worry about calling conventions is when you pass callbacks to API functions, like those in the Windows API:
Here, we declare
MyWndProc()
as having the__stdcall
convention (CALLBACK
is#define
'd as__stdcall
). This is needed because the operating system expects thatlpfnWndProc
points to aWNDPROC
, which uses theCALLBACK
convention.Just about every Windows API function that accepts a callback requires the callback functions to use the
__stdcall
convention, and since__cdecl
is usually the default, you must make this explicit (you would useCALLBACK
for window procedures).This is extremely important because stack corruption can occur if the operating system attempts to call a non-
__stdcall
function. Unfortunately enough people get this wrong that Windows will actually check for calling convention mismatch specifically for window procedures.While
__stdcall
is required for callback functions passed to WinAPI functions, functions that accept a variable number of arguments must use the__cdecl
calling convention, because only the caller will know how to properly pop the variable number of arguments off the stack. Since__cdecl
is usually the default, you don't need to explicitly specify__cdecl
for functions that accept a variable number of arguments.I personally haven't found a use for
__fastcall
, although I'm sure someone has.__clrcall
is relevant only if you're interacting with managed code.