您的位置:首页 > 其它

函数调用约定总结

2018-03-15 15:43 197 查看
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"的修饰方式下,是不允许函数重载的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息