函数调用约定总结

1. 函数调用约定,主要约束两件事
  • 参数传递顺序
  • 调用堆栈由谁(调用函数或被调用函数)清理

2. 常用函数调用约定: stdcall, cdecl, fastcall, thiscall, naked call

3. __stdcall表示:
  • 参数从右向左压入堆栈;
  • 函数被调用者清理堆栈;
  • C编译器函数名的修饰规则为:__functionname@number;(functionname为函数名,number为参数字节数)
  • C++编译器函数名的修饰规则为:?functionname@@YG******@Z;(“******”为函数返回值类型和参数类型表)
  • 使用场合:Windows API默认函数调用协议;

4. __cdecl表示
  • 参数从右向左压入堆栈;
  • 函数调用者清理堆栈;
  • C编译器函数名的修饰规则为:__functionname;(functionname为函数名,number为参数字节数)
  • C++编译器函数名的修饰规则为:?functionname@@YA******@Z;(“******”为函数返回值类型和参数类型表)
  • 使用场合:C/C++默认函数调用协议;
PS:
  • 函数实现和定义若使用不同的函数调用协议,则无法实现函数调用。
  • C语言和C++语言间若不进行特殊处理,也无法实现函数的互相调用。

实践举例:VS下查看调用约定
例子:

(1)__stdcall:WIN API约定,参数由右向左传递,由被调者清理堆栈;
编译后函数名为:_func@参数字节数(C编译);

(2)__cdcel:C/C++约定,参数由右向左传递,由调用者清理堆栈;
c编译后的函数名为:_func,
c++编译后的函数名为:_func@参数修饰串
这里的清理堆栈,是指对参数的清理,可通过反汇编查看。调用函数内部的参数由内部自己处理。

2. 函数名修饰
作用:用于修饰函数在编译后的函数名符号
extern "C":C风格函数名,在编译后函数名不变
C编译:

C++编译:

总结:不同的函数名修饰,导致函数符号不一致,从而使得函数重载的实现成为可能。在extern "C"的修饰方式下,是不允许函数重载的。

你可能感兴趣的:(C++学习总结)