visual C++编译器在编译函数时,会对函数名进行修饰。
如果没听过函数名修饰,咱们先做个试验,有个直观的认识。
#include "stdafx.h"
extern void func(int a,int b,long c);
int main(int argc, char* argv[])
{
func(1,2,5);
printf("Hello World!n");
return 0;
}
如以上代码所示,func函数只有声明,没有定义。 这个工程也之后这一个c文件。
我们编译工程,得到如下错误。
error LNK2001: unresolved external symbol "void __cdecl func(int,int,long)" (?func@@YAXHHJ@Z)
无法解析的外部符号?func@@YAXHHJ@Z ,看到了吗,func函数在后台的名字是?func@@YAXHHJ@Z
这就是对函数名的修饰。
为什么是?func@@YAXHHJ@Z 这样的呢?
函数名的修饰规则是:?+函数名+@@+调用规则+返回值类型+参数类型+@Z
调用规则VC++包含三种:
1.__cdecl在修饰规则里是YA,我们的例子中就是这种, ?func@@YAXHHJ@Z。
2.__stdcall在命令规则里是YG 。
3.__fastcall在命令规则里是YI。
这三种调用规则对于函数参数的传递方式和入栈顺序也不同,我们以后在讲。
返回值类型和参数类型如下:
X–void
D–char
E–unsigned char
F–short
H–int
I–unsigned int
J–long
K–unsigned long(DWORD)
M–float
N–double
_N–bool
U–struct
以上就是visual C++编译器的函数修饰规则。确切的说是C++语言的修饰规则。
那么 extern “C"是什么呢?
这个符号是告诉编译器,按C语言的修饰规则修饰。
我们加上“C",看看C语言的修饰规则是什么样的。
#include "stdafx.h"
extern "C" void func(int a,int b,long c);
int main(int argc, char* argv[])
{
func(1,2,5);
printf("Hello World!n");
return 0;
}
编译结果如下:
error LNK2001: unresolved external symbol _func
看到了吗,C语言的规则就是简单的在函数名前面,加了一个下划线。
那么我们为什么要折腾函数名的修饰规则呢?有什么用?
比如当你调用别人编译的库时,就需要知道对方是用什么规则编译的,你调用的时候也要用这种规则,不然就会提示“error LNK2001: unresolved external symbol XXXX” 这种错误。
当你编译工程时,提示此错误,可以查查是不是函数修饰规则的问题。
本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:dandanxi6@qq.com