何时使用调用约定

发布于 2024-09-13 07:42:51 字数 134 浏览 9 评论 0原文

使用不同调用约定的关键因素是什么?什么时候有人知道在不同场合使用特定的调用约定,例如__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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

街角迷惘 2024-09-20 07:42:51

大多数时候你不需要担心它。通常您会使用 __cdecl,但这只是因为这是 Visual C++ 中的默认设置。然而,C++ 成员函数在 Visual C++ 中默认使用 __thiscall 约定 在

一种(相当常见)的情况下,您真正​​需要担心调用约定的情况是,当您将回调传递给 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'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:

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

Here, we declare MyWndProc() as having the __stdcall convention (CALLBACK is #define'd as __stdcall). This is needed because the operating system expects that lpfnWndProc points to a WNDPROC, which uses the CALLBACK 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 use CALLBACK 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文