C/C++函数调用约定

[部分参考自https://blog.csdn.net/wenqiang1208/article/details/53163788]

最近工作中遇到了一些动态库对接的问题,查了下C语言函数调用约定的相关内容,做一下总结:
函数调用方式主要约定了关于函数参数入栈的顺序,以及栈资源回收的责任问题,因为这种原因,调用约定也直接影响了函数名修饰的方式
函数的名字修饰就是编译器在编译期间创建的一个字符串,比如一般的_cdecl约定,假设一个函数名为func(int a),那它展开后的名字修饰为的为_func。用来指明函数的定义或原型。链接器或其他工具有时需要指定函数的名字修饰来定位函数的正确位置。多数情况下程序员并不需要知道函数的名字修饰,链接器或其他工具会自动区分他们。当然C语言的区分方式相对简单,C++程序由于存在重载函数等特殊情况,所以修饰规则会复杂一些,而且没什么特定的规律,不同编译器版本会有略微的差异,下面将分别介绍C/C++下三种常见的调用约定。

__cdecl

C语言默认的调用约定,一般不另外说明的话,C语言编程时默认就使用这种约定。
它约定了函数参数的入栈顺序是从右到左入栈,
函数返回之前,调用者负责恢复堆栈资源。
修饰规则上,仅仅在函数名前面加一个下划线,所以C语言调用约定是允许函数参数不固定的。

__stdcall

stdcall很多时候被称为pascal调用约定,因为pascal是早期很常见的一种教学用计算机程序设计语言,其语法严谨,使用的函数调用约定就是stdcall。一般WinAPI32就是用的这种约定。
它约定了函数参数的入栈顺序是从右到左入栈。
函数返回之前,被调用的函数自己负责恢复堆栈资源。
修饰规则上,是在函数名前面加一个下划线,后面再加上一个@和参数的字节数,比如_func@4。

__fastcall

_fastcall函数调用约定在可能的情况下使用寄存器传递参数
它的传递规则不固定,通常约定了前两个 DWORD类型的参数或较小的参数使用ECX和EDX寄存器传递,从左往右传入。其余参数按照从右向左的顺序入栈。
函数返回之前,被调用函数自己负责清除栈中的参数。
函数名自动加前导的下划线,后面紧跟@符号,其后紧跟着参数的尺寸。

C++编译器的函数名修饰规则

C++的函数名修饰规则有些复杂,但是信息更充分,通过分析修饰名不仅能够知道函数的调用方式,返回值类型,参数个数甚至参数类型。不管__cdecl,__fastcall还是__stdcall调用方式,函数修饰都是以一个“?”开始,后面紧跟函数的名字,再后面是参数表的开始标识和返回值的类型以及按照参数类型代号拼出的参数表,最后结束标志。
对于__stdcall方式,参数表的开始标识是“@@YG”,比如?func@@YG******@Z
对于__cdecl方式,参数表的开始标识是“@@YA”,比如?func@@YA******@Z
对于__fastcall方式,参数表的开始标识是“@@YI”,比如?func@@YI******@Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值