C++中的函数调用约定有哪些?__cdecl与__stdcall的区别【底层知识】
发布时间 - 2025-12-26 00:00:00 点击率:次__cdecl与__stdcall的核心区别在于栈清理责任:__cdecl由调用方清栈,__stdcall由被调函数清栈;两者压栈顺序均为从右向左,但名字修饰不同(__cdecl为\_Func,__stdcall为\_Func@N),影响链接与动态调用。
Windows平台下C++函数调用约定主要有 __cdecl、__stdcall、__fastcall、__thiscall 和 __vectorcall(较新版本VC支持)。其中最基础、最常被问及的是 __cdecl 与 __stdcall,它们的核心差异在于谁来清理栈空间和参数压栈顺序——而这直接关系到函数能否被正确调用、链接和导出。
参数压栈顺序:两者完全一致
__cdecl 和 __stdcall 都采用从右向左的压栈顺序。例如:
func(a, b, c);
实际入栈顺序是:c → b → a。这点没有区别,不必担心调用时参数错位。
栈平衡责任:关键区别所在
函数调用后,栈指针(ESP)必须恢复到调用前位置,这个“清理栈”的动作由谁完成,决定了调用约定的本质差异:
-
__cdecl:由调用方(caller)负责清栈。编译器在每次调用后生成
add esp, N指令(N为参数总字节数)。 -
__stdcall:由被调用函数(callee)负责清栈,即函数返回前执行
ret N(带立即数的 ret 指令),自动修正栈顶。
这意味着:同一个函数如果声明为 __stdcall 却被按 __cdecl 方式调用(或反之),会导致栈失衡——轻则局部变量错乱,重则程序崩溃,且问题往往延迟暴露,极难调试。
名字修饰(Name Mangling)规则不同
为了支持函数重载和调用约定识别,编译器会对函数名进行修饰。两者典型规则如下(以32位x86为例):
-
__cdecl:函数名前加一个下划线,如
_MyFunc;若带参数,不体现参数大小,仍为_MyFunc。 -
__stdcall:函数名前加下划线,**后缀加 @ + 参数总字节数**,如三个 int 参数(12字节)→
_MyFunc@12。
因此,在 .def 文件导出、GetProcAddress 动态获取、或混用 C/C++ 与汇编时,必须严格匹配调用约定,否则链接器报 “unresolved external” 或运行时报 “procedure not found”。
适用场景与默认行为
- __cdecl 是 C/C++ 默认调用约定(除非显式指定),尤其适合可变参数函数(如 printf),因为只有调用方知道实际传了多少参数,必须由它清栈。
- __stdcall 主要用于 Windows API 函数(如 MessageBoxA、CreateWindowEx),也是 COM 接口的标准约定。它减少调用方代码体积(无需每处都清栈),利于接口统一。
- __fastcall 尝试用寄存器(ECX、EDX)传前两个DWORD参数,其余仍压栈;__thiscall 是非静态成员函数的默认约定(this 指针通常放 ECX)。
基本上就这些。理解它们不是为了手写汇编,而是读懂链接错误、排查崩溃、正确使用 Win32 API 或编写 DLL 导出函数时的关键底层支撑。
# word
# windows
# cad
# 字节
# 栈
# c++
# win
# 区别
# 成员函数
# printf
# 局部变量
# 可变参数
# int
# 指针
# 接口
# 函数重载
# this
# 下划线
# 的是
# 均为
# 会对
# 为例
# 而这
# 谁来
# 关系到
# 主要用于
# 新版本
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
JavaScript如何操作视频_媒体API怎么控制播放
香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南
如何挑选最适合建站的高性能VPS主机?
HTML5段落标签p和br怎么选_文本排版常用标签对比【解答】
新三国志曹操传主线渭水交兵攻略
Laravel Artisan命令怎么自定义_创建自己的Laravel命令行工具完全指南
Laravel软删除怎么实现_Laravel Eloquent SoftDeletes功能使用教程
Laravel如何使用Facades(门面)及其工作原理_Laravel门面模式与底层机制
Laravel怎么进行数据库事务处理_Laravel DB Facade事务操作确保数据一致性
桂林网站制作公司有哪些,桂林马拉松怎么报名?
如何在万网自助建站中设置域名及备案?
Laravel如何实现模型的全局作用域?(Global Scope示例)
Laravel怎么使用artisan命令缓存配置和视图
Laravel怎么实现模型属性转换Casting_Laravel自动将JSON字段转为数组【技巧】
如何利用DOS批处理实现定时关机操作详解
laravel怎么配置和使用PHP-FPM来优化性能_laravel PHP-FPM配置与性能优化方法
Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】
手机怎么制作网站教程步骤,手机怎么做自己的网页链接?
利用JavaScript实现拖拽改变元素大小
Laravel怎么在Blade中安全地输出原始HTML内容
Laravel如何实现用户注册和登录?(Auth脚手架指南)
UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】
如何用VPS主机快速搭建个人网站?
如何在阿里云服务器自主搭建网站?
如何在香港免费服务器上快速搭建网站?
济南网站建设制作公司,室内设计网站一般都有哪些功能?
javascript中闭包概念与用法深入理解
如何在云主机快速搭建网站站点?
微信小程序 配置文件详细介绍
Laravel数据库迁移怎么用_Laravel Migration管理数据库结构的正确姿势
Laravel全局作用域是什么_Laravel Eloquent Global Scopes应用指南
如何在万网ECS上快速搭建专属网站?
Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用
Laravel如何与Vue.js集成_Laravel + Vue前后端分离项目搭建指南
如何快速生成可下载的建站源码工具?
非常酷的网站设计制作软件,酷培ai教育官方网站?
深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?
Laravel如何发送邮件_Laravel Mailables构建与发送邮件的简明教程
香港服务器网站生成指南:免费资源整合与高速稳定配置方案
潮流网站制作头像软件下载,适合母子的网名有哪些?
昵图网官网入口 昵图网素材平台官方入口
Laravel如何实现数据导出到CSV文件_Laravel原生流式输出大数据量CSV【方案】
车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?
Laravel如何处理和验证JSON类型的数据库字段
谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复
电商网站制作价格怎么算,网上拍卖流程以及规则?
Win11怎么设置默认图片查看器_Windows11照片应用关联设置
Laravel如何实现RSS订阅源功能_Laravel动态生成网站XML格式订阅内容【教程】
千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】
Laravel的Blade指令怎么自定义_创建你自己的Laravel Blade Directives


dcall由被调函数清栈;两者压栈顺序均为从右向左,但名字修饰不同(__cdecl为\_Func,__stdcall为\_Func@N),影响链接与动态调用。