C/C++ 函数调用约定详解:stdcall、cdecl 与 name mangling

小满
小满
发布时间:2026-10-14| 3人浏览过
原创

C/C++ 函数的调用约定决定了参数如何传递、谁负责清理堆栈以及函数名在二进制文件中的表现形式。常见的调用方式包括 stdcall、cdecl、fastcall 和 thiscall,它们在不同场景下各有优劣,正确理解这些约定对于编写高效的系统级代码至关重要。

调用约定的核心要素

函数调用时,计算机通常使用栈(Stack)来存储传递给函数的参数。栈是一种先进后出的数据结构,操作主要包含压栈(Push)和弹出栈(Pop)。在高级语言层面,调用约定主要解决两个关键问题:

  1. 当参数个数多于一个时,按照什么顺序把参数压入堆栈。
  2. 函数调用结束后,由谁来把堆栈恢复原状。

常见调用方式详解

第1步:理解 stdcall 调用方式

适用场景:Windows API 函数常用的标准调用方式,强调节省内存开销。

入口与声明:在 Microsoft C++ 编译器中,可通过 PASCAL、WINAPI 或 CALLBACK 宏指定,或直接使用 _stdcall 关键字。

int _stdcall function(int a, int b);

关键特性:

  • 压栈顺序:参数从右向左依次压入堆栈。
  • 堆栈清理:由被调用函数自己恢复堆栈(这是其相对于 cdecl 的最大区别)。
  • 名称修饰:函数名自动加前导下划线,接着是 @ 符号和参数的字节数,例如 _function@8。

第2步:掌握 cdecl 调用方式

适用场景:C 语言的默认调用方式,支持可变参数列表(如 printf)。

入口与声明:不加修饰符即为 C 调用方式,也可显式指定 _cdecl。

int function(int a, int b);
// 或
int _cdecl function(int a, int b);

关键特性:

  • 压栈顺序:参数从右向左依次压入堆栈。
  • 堆栈清理:由调用者在函数返回后恢复堆栈。因此它允许函数拥有不固定的参数个数。
  • 名称修饰:仅在函数名前加前导下划线,如 _function。

第3步:了解 fastcall 快速调用

适用场景:对性能要求较高,且参数较少的场景。

入口与声明:通过 _fastcall 指定。

关键特性:

  • 寄存器传递:前两个 DWORD 类型的参数分别通过 ecx 和 edx 寄存器传递,而非压栈。
  • 剩余参数:后续参数仍从右向左压入堆栈。
  • 堆栈清理:由被调用函数清理堆栈。
  • 名称修饰:同 stdcall,格式通常为 @function@8(注意前缀是一个 @)。

第4步:区分 thiscall 成员函数调用

适用场景:C++ 类成员函数的默认调用方式。

关键特性:

  • 特殊约束:thiscall 是唯一不能显式写在代码中的调用修饰符,由编译器自动应用。
  • 指针传递:如果参数个数确定,this 指针通过 ecx 寄存器传递给被调用者;如果参数个数不确定,this 指针会在所有参数压栈后被压入堆栈。
  • 行为类比:固定参数时类似 stdcall,可变参数时类似 cdecl。

函数名修饰(Name Mangling)规则

为了保证链接时的唯一性,编译器会对函数名进行修改。C 语言和 C++ 的修饰规则有所不同。

C 语言修饰规则

  • __stdcall:_functionname@N(N为参数字节数)。
  • __cdecl:_functionname。
  • __fastcall:@functionname@N。

注意:上述规则均不改变大小写,这与传统的 PASCAL 调用约定(全大写无修饰)不同。

C++ 语言修饰规则

C++ 由于支持函数重载,修饰规则更为复杂,旨在保留类型信息:

  • 通用格式:?functionname@@Y...Z。
  • 标识符说明:? 开头,@@YG 表示 __stdcall,@@YA 表示 __cdecl,@@YI 表示 __fastcall,结尾以 Z 结束。
  • 类型代号:X 代表 void,D/E/F/H/I/J/K/M/N 分别代表各种基本数据类型,PA0 等用于表示指针和数组。
  • 示例:
// int Test1(char *var1, unsigned long)
// ?Test1@@YGHPADK@Z

// void Test2()
// ?Test2@@YGXXZ

总结与注意事项

VC++ 对函数的默认声明通常是 __cdecl,这使得函数只能被 C/C++ 调用程序正确链接。在混合编程或编写动态链接库时,确保声明调用方式和实际调用方式一致至关重要,否则会导致栈失衡或程序崩溃。

以上就是 C/C++ 函数调用约定及名称修饰规则的详细内容,更多关于 C++ 底层机制的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。