与函数堆栈密切相关的就是函数调用规范,即调用约定。函数调用规范决定了函数调用的实参压栈,退栈及堆栈释放的方式,以及函数名改编的方案,也即命名规范,windows下常用的调用约定有:
_cdecl:
这是C/C++函数的默认调用规范,参数从右向左依次传递并压入堆栈,由调用函数负责堆栈的清退,因此这种方式有利于传递可变的参数给被调用函数(因为只有调用函数才知道才知道他给被调用函数传递多少个参数及他们的类型)如printf()函数(函数的实现不需要知道实参的类型和个数)。_stdcall:
这是Win API函数使用的调用规范。参数从右向左依次传递并压入堆栈,由被调用函数负责堆栈的清退。该规范生成的函数代码比_cdecl更小,但 当函数有可变的参数时会转为_cdecl规范。在Windows中,宏WINAPI,CALLBACK都定义为_stdcall。- _thiscall:
是c++非静态成员函数的默认调用规范,不能使用个数可变的参数。当非静态成员函数的时候,this指针直接保存在ECX寄存器中而非压入函数堆栈。其他方面与_stdcall相同。 - _fastcall:
该规范修饰的函数的实参将被直接传递到CPU寄存器中而不是内存堆栈中(这就是“快速调用”的含义)。堆栈清退由被调用函数负责,该规范不能用于成员函数。
函数必须指定一个调用规范。特别是在模块之间的接口中,每一个函数原型的调用规范必须与其实现的调用规范保持一致,否则会出现编译错误。
(类的静态成员函数和友元函数的调用规范都不是_thiscall,他们是由函数本身指定或者工程设定的)。