调用约定(Calling Convention) 是计算机编程中一个比较底层的设计,它主要涉及:
在C和C++中有几种调用约定:__cdecl
, __stdcall
, __fastcall
, __thiscall
, __clrcall
, __vectorcall
。下面首先介绍几种调用约定。
C Declaration Calling Convention,C声明调用约定。它是C和C++默认的调用约定。特点:
Standard Calling Convention,标准调用约定。又称为Pascal Convention。特点:
Fast Calling Convention,快速调用约定。通过使用寄存器解决效率问题。特点:
主要用于解决类中this指针传递的问题,使用寄存器来传递this指针。参数从右往左压栈,返回方式同__stdcall.
__clrcall是C++ .Net里面的。
要求尽可能在寄存器中传递参数。函数名改编为”@@函数名@参数字节数十进制”。这是微软自己添加的标准。 总结
除了__cdecl
(以及__clrcall
),其他的都是被调用者清除堆栈。
在C语言中不存在重载,因此不需要担心同名函数问题,但是在C++中,使用C中的函数名修饰方式就存在问题。对于重载的函数,仅仅凭函数名和参数内存大小无法完全区分;类的成员函数表示并没有说明。所以在C++中,对于函数名改编需要一套策略。函数名格式大致如?FuncName@@YGXZ
这种形式。
?
开始,后面接函数名。@@YG
、@@YA
、@@YI
,分别代表stdcall、cdecl、fastcall。@Z
结束,如果函数没有参数,则直接以Z
结束。参数符号如下:
所以int __stdcall fa();
可以改编为:?fa@@YGHXZ
;char* fb(int,bool);
改编为?fb@@YAPADH_N@Z
。
所以在C++中函数名改编和C不同,如果需要遵循C中的改编方式,可以使用extern "C"{}
。
类的成员函数的调用方式为thiscall,其函数名修饰方式和普通函数有些差别。成员函数名改编需在函数名和参数中间插入类名。且需要指定函数一些性质,如
ABV1
。如:
?FuncA@ClassA@@QAEXH@Z
表示void ClassA::FuncA(int);
。?FuncB@ClassA@@QAEXABV1@Z
表示void ClassA::FuncB(const ClassA&);
如果您觉得文章对您有用能够解决您的问题,欢迎您通过扫码进行打赏支持,谢谢!