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

  1. 1、本文档共6页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
C语言函数调用方式的区别

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)

wuyoujun92 + 关注
实名认证
内容提供者

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

1亿VIP精品文档

相关文档