函数调用约定¶
当一个函数被调用时,参数会被传递给这个函数,返回值会被返回给调用者。函数调用约定主要约束了三件事:
- 参数传递顺序。
- 堆栈维护职责。
- 名称修饰约定。
参考:Calling Conventions | Microsoft Learn
stdcall¶
Win 32 API 函数绝大部分都是采用 __stdcall 调用约定的。WINAPI 其实也只是 __stdcall 的一个别名而已。
#define WINAPI __stdcall
| 实现 | |
|---|---|
| 参数传递顺序 | 从右向左 |
| 堆栈维护职责 | 被调用的函数从堆栈中弹出自己的参数 |
| 名称修饰约定 | _ 作为名称的前缀,名称后跟 @ 符号和所有参数占用的字节数(十进制) |
例如
int32_t __stdcall func(int32_t a, double b);
修饰后的名称为 _func@12。
由于该调用约定是被调用方清理堆栈,因此编译器会对 vararg 函数使用 __cdecl。
cdecl¶
__cdecl 是 C Declaration 的缩写,是 C/C++ 程序的默认调用约定。
| 实现 | |
|---|---|
| 参数传递顺序 | 从右向左 |
| 堆栈维护职责 | 调用函数从堆栈中弹出参数 |
| 名称修饰约定 | _ 作为名称的前缀,但导出使用 C 链接的 __cdecl 函数时除外 |
由于堆栈由调用方清理,因此它可以执行 vararg 函数,但该调用约定创建的可执行文件比 __stdcall 更大,因为它要求每个函数调用都包含堆栈清理代码。