函数的调用约定方式及函数的名称修饰符.pdfVIP

函数的调用约定方式及函数的名称修饰符.pdf

  1. 1、本文档共7页,可阅读全部内容。
  2. 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  5. 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  6. 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  7. 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  8. 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
函数的调用约定方式及函数的名称修饰符.pdf

几乎每种编程语言都有函数的概念,而作为函数,就一定有参数的概念; 一般来说,参数的传递是通过栈来实现的,栈是一种先入后出的数据结构,使用Push()把参数压 入栈中,使用Pop()把参数弹出栈,而且Push()和Pop()必须成对出现。 现在称为标准调用的就是PASCAL 语言的调用方式:反序压栈,正序出栈;这样做的确有好处, 因 为压栈行为是编译器编译好的(编译时行为),虽然麻烦,但是只在编译阶段做一次,而出栈行为 是程序实际运行时的调用行为(运行时行为),需要反复多次执行,使用正序的参数(正序出栈), 对被调函数来说,处理上方便不少; 而Windows 使用的调用方式跟PASCAL 语言的调用方式是一样的,所以, 以前老的C 程序员编 写Windows 程序时需要使用关键字PASCAL 来明确指出使用PASCAL 的调用规则,现在一般不 再使用PASCAL 关键字了,而使用__stdcall 说明符,表示使用的是标准调用; 使用C/C++语言开发软件的程序员经常碰到这样的问题: 有时候是程序编译没有问题,但是链接的时候总是报告函数不存在(经典的LNK 2001 错误), 有时候是程序编译和链接都没有错误,但是只要调用库中的函数就会出现堆栈异常。这些现 象通常是出现在C 和C++ 的代码混合使用的情况下或在C++程序中使用第三方的库的情况下 (不是用 C++语言开发的) ,其实这都是函数调用约定(Calling Convention) 和函数名修饰 (Decorated Name)规则惹的祸。 函数调用约定方式决定了函数参数入栈的顺序,是由调用者函数还是被调用函数负责清除栈 中的参数等问题,而函数名修饰规则决定了编译器使用何种名字修饰方式来区分不同的函数, 如果函数之间的调用约定不匹配或者名字修饰不匹配就会产生以上的问题。本文分别对 C 和 C++这两种编程语言的函数调用约定和函数名修饰规则进行详细的解释,比较了它们的 异同之处,并举例说明了以上问题出现的原因。 ******************************************************************************* 一、函数的调用约定方式(Calling Convention): 有很多种方式,常见的有__cdecl 、__stdcall 、__fastcall,C++ 的编译器还支持__thiscall 方式,不少 的C/C++编译器还支持naked call 方式; ******************************************************************************* 1.__cdecl 方式(编译器的命令行参数是/Gd): __cdecl 是C/C++编译器默认的函数调用约定; 所有非C++成员函数和那些没有用__stdcall 或__fastcall 声明的函数都默认是__cdecl 方式。 函数参数按照从右向左的顺序入栈,函数调用者负责清除栈中的参数。由于每次函数调用 都要由编译器产生清除/ 还原堆栈的代码, 所以使用__cdecl 方式编译出来的程序比使用 __stdcall 方式编译出来的程序要大很多,但是__cdecl 调用方式是由调用者函数负责清空栈中 的函数参数,所以,__cdecl 方式支持可变参数, 比如 printf 和 Windows 的 API wsprintf 就是 __cdecl 调用方式; 对于C 函数,__cdecl 方式的名字修饰符约定是在函数名称前面添加一个下划线; 对于C++ 函数,除非特别使用extern C,C++函数使用不同的名字修饰符; 2.__stdcall 方式(编译器的命令行参数是/Gz): _stdcall 是Pascal 程序的缺省调用方式,通常用于Win32 Api 中, 大多数Windows 的API 也 是__stdcall 调用约定。 __stdcall 函数调用约定将函数参数从右向左入栈,除非使用指针或引用类型的参数,所有 参数采用传值方式传递,由被调用函数负责清除栈中的参数。 对于 C 函数,__stdcall 的名称修饰方式是在函数名称前面添加下划线,在函数后面添加@符号 和函数参数所占用的内存字节大小;例如: _function_name@number; 3.__fastcall 方式(编译器的命令行参数是/Gr): __fastcall 函数调用约定在可能的情况下

您可能关注的文档

文档评论(0)

ziyouzizai + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档