C语言函数调用方式的区别.docVIP

  1. 1、本文档共6页,可阅读全部内容。
  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文档。上传文档
查看更多
C语言函数调用方式的区别 通常在使用VC进行函数定义时会指定该函数调用方式,诸如:   int __stdcall max(int a, int b)   {   return ab?a:b;   }   int __cdecl min(int a, int b)   {   return ab?a:b;   }   bool __fastcall equal(int a, int b)   {   return a=b?true:false;   }   首先,让我们来分个类,调用方法分为两大类另加一个较特殊的__thiscall.   第一类:__stdcall类 别名:WINAPI,CALLBACK,PASCAL。该类特点是:主调函数负责参数入栈,由函数本身负责栈的恢复。   第二类:__cdecl类 别名:C/C++中默认调用方式,若你定义函数未指定函数调用约定(Calling Conventions),例如在VC6中下面两个函数的调用约定是等价的:   int max(int a, int b)   {   return ab?a:b;   }   int __cdecl min(int a, int b)   {   return ab?a:b;   }   该类调用约定的特点是:由主调函数负责参数入栈,并由主调函数负责线的恢复。   第三类:__thiscall 该类比较特殊,只用于类成员函数调用,你甚至不能强制指定这个函数调用约定。它是由C/C++编译器自动添加的。在C/C++中类成员函数会默认传入一个this指针,对于此,在默入情况下,C/C++中类成员函数通过此类调用约定来指定this指针。   接着介绍一下__thiscall,__thiscall是关于类的一种调用方式。   它与其他调用方式的最大区别是:   __thiscall对每个函数都增加了一个类指针参数   class aa   {   void bb(int cc);   };   实际上bb的函数原形是void bb(aa this, int cc);   __cdecl的调用方式介绍: C和C++缺省调用方式   例子:   void Input( int m,int n);/*相当于void __cdecl Input(int m,int n);*/   以下是相应的汇编代码:  lea eax,[ebp-8] ;取[ebp-8]地址(ebp-8),存到eax   0040106B push eax ;然后压栈   0040106C lea ecx,[ebp-4] ;取[ebp-4]地址(ebp-4),存到ecx   0040106F push ecx ;然后压栈  call @ILT+5(Input) (0040100a);然后调用Input函数  add esp,8 ;恢复栈   从以上调用Input函数的过程可以看出:在调用此函数之前,首先压栈ebp-8,然后压栈ebp-4,然后调用函数Input,最后Input函数调用结束后,利用esp+8恢复栈。由此可见,在C语言调用中默认的函数修饰_cdecl,由主调用函数进行参数压栈并且恢复堆栈。   下面看一下:地址ebp-8和ebp-4是什么? 在VC的VIEW-debug windows-Registers,显示寄存器变量值,然后在选debug windows-Memory,输入ebp-8的值和ebp-4的值(或直接输入ebp-8和-4),看一下这两个地址实际存储的是什么值,实际上是变量n 的地址(ebp-8),m的地址(ebp-4)。   由此可以看出:在主调用函数中进行实参的压栈并且顺序是从右到左。另外,由于实参是相应的变量的引用,也证明实际上引用传递的是变量的地址(类似指针)。   总结:在C或C++语言调用中默认的函数修饰_cdecl,由主调用函数进行参数压栈并且恢复堆栈,实参的压栈顺序是从右到左,最后由主调函数进行堆栈恢复。由于主调用函数管理堆栈,所以可以实现变参函数。另外,命名修饰方法是在函数前加一个下划 线(_)。   _stdcall调用约定介绍:实际上就是PASCAL,CALLBACK,WINAPI   例子:   void WINAPI Input( int m,int n);   看一下相应调用的汇编代码:  lea eax,[ebp-8]   0040106B push eax   0040106C lea ecx,[ebp-4]   0040106F push ecx  call @ILT+5(Input) (0040100a)   从以上调用Input函数的

文档评论(0)

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

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

1亿VIP精品文档

相关文档