__stdcall,__fastcall,__cdecl等函数说明符详解

来源:互联网 发布:mac repo 安装下载 编辑:程序博客网 时间:2024/06/07 02:27

__stdcall,__fastcall,__cdecl用于确定以下三方面函数调用信息:

1。将函数参数推送到堆栈上的顺序。
2。是由调用方函数还是由被调用函数在调用结束时从堆栈中移除参数。
3。编译器用来标识各个函数的名称修饰约定。

 


__cdecl 细节
对于 C,__cdecl 命名约定使用以下划线 ( _ ) 开头的函数名;不执行任何大小写转换。除非声明为 extern "C",否则 C++ 函数将使用不同的名称修饰方案。有关更多信息,请参阅修饰名。

__fastcall 细节
某些 __fastcall 函数参数在寄存器 x86 Specific —> ECX 和 EDX END x86 Specific 中传递,其余参数则被从右到左推送到堆栈上。被调用例程在返回之前从堆栈中弹出这些参数。/Gr 通常减少执行时间。

注意 在对用内联程序集语言编写的任意函数使用 __fastcall 调用约定时,一定要小心。您对寄存器的使用可能与编译器对它们的使用发生冲突。
对于 C,__fastcall 命名约定使用以“at”符 (@) 开头的函数名,后跟函数参数大小(以字节为单位)。不执行任何大小写转换。编译器使用下列命名约定模板:

@function_name@number
注意 Microsoft 不保证不同编译器版本之间的 __fastcall 调用约定的实现相同。例如,16 位编译器与 32 位编译器的实现就不同。
当使用 __fastcall 命名约定时,请使用标准包含文件。否则将获取无法解析的外部引用。

__stdcall 细节
__stdcall 函数的参数被从右到左推送到堆栈上,被调用函数在返回之前从堆栈中弹出这些参数。

对于 C,__stdcall 命名约定使用以下划线 ( _ ) 开头的函数名,后跟“at”符 (@) 和函数参数大小(以字节为单位)。不执行任何大小写转换。编译器使用下列命名约定模板:

_functionname@number
x86 Specific—>

此选项对 C++ 方法和函数的名称修饰无效。除非声明为 extern "C",否则 C++ 方法和函数将使用不同的名称修饰方案。有关更多信息,请参阅修饰名。

 

C 和 C++ 程序中的函数在内部通过其修饰名加以识别。修饰名是在编译函数定义或函数原型期间由编译器创建的字符串。

当指定 LINK 或其他工具的函数名时,有时需要修饰名。对于需要修饰名的情况,请参考正在使用的工具的文档,获取详细信息。


使用修饰名
修饰名 | C++ 修饰名的格式和 C 修饰名的格式
大多数情况下,无需知道函数的修饰名。LINK 和其他工具通常可以处理未修饰形式的名称。

但是,某些情况要求指定修饰形式的名称。必须指定重载的 C++ 函数和特殊成员函数(如构造函数和析构函数)的修饰名,以使 LINK 和其他工具可以与该名称匹配。在引用 C 或 C++ 函数名的程序集源文件中也必须使用修饰名。

警告 如果更改函数名、类、调用约定、返回类型或任何参数,修饰名不再有效。必须获取函数名的新版本并在所有指定了修饰名的位置使用。

 

查看修饰名请参见
修饰名
编译包含函数定义或函数原型的源文件之后,可以获取函数名的修饰形式。若要在程序中检查修饰名,请执行下列操作之一:

1.使用列表
2.使用 DUMPBIN 工具

可以使用 undname.exe 将修饰名转换为未修饰形式。例如,

C:/>undname ?func1@a@@AAEXH@Z
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation 1981-2000. All rights reserved.Undecoration
of :- "?func1@a@@AAEXH@Z"
is :- "private: void __thiscall a::func1(int)"