1、 声明外部变量
//A.cpp
int i;
void main()
{
}
//B.cpp
int i;
这两个文件极为简单,在A.cpp中我们定义了一个全局变量i,在B中我们也定义了一个全局变量i。
我们对A和B分别编译,都可以正常通过编译,但是进行链接的时候,却出现了错误,错误提示如下:
Linking...
B.obj : error LNK2005: "int i" (?i@@ 3HA) already defined in A.obj
Debug/A.exe : fatal error LNK1169: one or more multiply defined symbols found
Error executing link.exe.
A.exe - 2 error(s), 0 warning(s)
//A.cpp
void main()
{
i = 100; //试图使用B中定义的全局变量
}
//B.cpp
int i;
编译结果如下:
Compiling...
A.cpp
C:/Documents and Settings/wangjian/桌面/try extern/A.cpp(5) : error C2065: 'i' : undeclared identifier
Error executing cl.exe.
A.obj - 1 error(s), 0 warning(s)
编译错误。其实出现这个错误是意料之中的,因为:文件中定义的全局变量的可见性扩展到整个程序是在链接完成之后,而在编译阶段,他们的可见性仍局限于各自的文件。
//A.cpp
extern int i;
void main()
{
i = 100; //试图使用B中定义的全局变量
}
//B.cpp
int i;
顺利通过编译,链接。
2、 在C++文件中调用C方式编译的函数
int i;
int func(int t)
{
return 0;
}
void main()
{
}
以C方式编译的结果:
COMM _i : DWORD
PUBLIC _func
PUBLIC _main
以C++方式编译的结果:
PUBLIC ?i@@ 3HA ; i
PUBLIC ?func@@YAHH@Z ; func
PUBLIC _main
可见,C方式编译下,变量名和函数名之前被统一加上了一个下划线,而C++编译后的结果却复杂的多,i变成了?i@@ 3HA,func变成了?func@@YAHH@Z。C++中的这种看似复杂的命名规则是为C++中的函数重载,参数检查等特性服务的。
多文件程序中的函数调用
一般情况下,工程中的文件都是CPP文件(以及头文件)。如下面的程序仅包含两个文件:A.CPP和B.CPP:
//A.CPP
void func();
void main()
{
func();
}
//B.CPP
void func()
{
}
程序的结构是这样的:在文件B.CPP中定义了一个函数void func(),main函数位于文件A.CPP,在main函数中调用了B中定义的函数func()。要在A中调用B中定义的函数,必须要加上该函数的声明。如本例中的void func();就是对函数func()的声明。
需要注意的是,一般的程序都是通过包含头文件来完成函数的声明。拿本例来说,一般是创建一个头文件B.H,在头文件中加入声明语句void func(); 并且在A.CPP中加入包含语句:#include “B.H”。
在C++程序中,头文件的功能从函数声明被扩展为类的定义。
//A.CPP
void func();
void main()
{
func();
}
//B.C
void func()
{
}
Linking...
A.obj : error LNK2001: unresolved external symbol "void __cdecl func(void)" (?func@@YAXXZ)
Debug/A.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
A.exe - 2 error(s), 0 warning(s)
如果B文件也是按照C++方式编译的,那么B中的func函数名也会被编译器改成?func1@@YAXXZ,这样的话,就没有任何问题。
对A.CPP和B.C分别编译,都没有问题,但是链接时出现错误。 原因就在于不同的编译方式产生的冲突。 对于文件A,是按照C++的方式进行编译的,其中的func()调用被编译成了 call ?func1@@YAXXZ//A.CPP
extern "C"
{
void func();
}
void main()
{
func();
}
3、 补充
同2一样,仍然是C,C++混合编程的情形,考虑下面的程序:
/A.CPP
extern int i;
void main()
{ i = 100; }
//B.C
int i;
程序很简单:在文件B.C中定义了一个全局变量i,在A.CPP中使用了这个全局变量。
这是因为,在C方式编译下,i被重命名为_i,而在C++方式下,i会被重命名为?i@@ 3HA。
因而,我们只用extern int i;来声明还不够,必须告诉编译器,全局变量i是以C方式编译的,
它会被重命名为_i,而不是?i@@ 3HA。
我们修改A.CPP,如下: 程序正常通过编译和链接。
//A.CPP
extern "C"
{
int i;
}
void main()
{
i = 100;
}
我们察看一下汇编代码,发现语句i = 100;被编译成了mov DWORD PTR _i, 100。
Linking...
A.obj : error LNK2001: unresolved external symbol "int i" (?i@@ 3HA)
Debug/A.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
A.exe - 2 error(s), 0 warning(s)