stdcall与cdecl,thiscall 等等 (阅读Firefox源码引发的血案)

来源:互联网 发布:淘宝客淘口令 编辑:程序博客网 时间:2024/05/01 21:01

今天阅读Firefox源码时,遇到一个问题:

在NsCacheEntryDescriptor中,有许多函数,他们的原型没有定义在头文件中,但是cpp文件中却有函数的实现。(这个问题我暂时没有想到为什么)

而这些函数都有一个统计的前缀宏:NS_IMETHODIMP

不明所以,因此google it. 找到答案:

这是一个宏,和微软COM中的STDMETHOD和STDMETHODIMP类似
在gecko sdk的nscore.h中可以找到相关的定义

代码
#define NS_IMETHOD_(type) virtual type __stdcall
#define NS_IMETHODIMP_(type) type __stdcall
 
原来就是一个函数约束,问题是__stdcall是啥的。倒是已经看过好几回了。就是一直没打过招呼。
 
那这次就打打吧:http://blog.chinaunix.net/u/14933/showart_114098.html
找着篇好文章,跟大家分享一下,下面我的学习记录。
 
首先明确这两个约定是关于函数调用的,而且涉及函数调用的两个问题:
1. 按照什么顺序将参数入栈。
2. 函数结束时,由函数本身还是调用者负责将栈恢复。
 
先说说__stdcall, 在Microsoft 的C/C++中,宏PASCAL和WINAPI,CALLBACK就是这个__stdcall。 这个约定叫做Pascal调用方式。关键点:
1. 从右向左入栈
2. 函数本身负责修改堆栈。
3. 编译后的函数名是下划线加函数名加@加参数尺寸
 
再说__cdecl(我到现在还不知掉他的全称是什么) 他是C编译器的默认约束,如果函数前面不加约束,那么就是默认他了。
1. 从右向左入栈
2. 函数本身不负责修改堆栈,即最后没有清除栈的操作。
 
博文里面提到这种 不负责修改堆栈的特性,使得C允许不定长的参数。我不是很理解为什么?因为据博文后面的解释,因为参数是从右到做压栈的,那么只要其中不定长参数左边有一个参数能够描述参数个数,那么就可以知道不定长参数的位置了。这个可以理解,但是这个跟最后不清除栈有什么关系呢?
 
还有一个是thiscall,这个是c++的类成员函数的缺省约束。但是不用写,写了也没用,因为不是关键字。
关于这个约定,他是结合了stdcall和cdecl的,对确定参数的,他的功用类似stdcall,当参数不确定,则类似于cdecl。
这个留待日后研究吧。