查看完整版本: 解析“extern”

CPP 2008-10-1 20:03

解析“extern”

[b][font=Times New Roman][size=3]1、[/size]
[/font][/b][b][size=3][font=宋体]声明外部变量[/font]
[/size][/b]

[font=宋体][size=3]现代编译器一般采用按文件编译的方式,因此在编译时,各个文件中定义的全局变量是[/size][/font]
[size=3][font=宋体]互相透明的,也就是说,在编译时,全局变量的可见域限制在文件内部。下面举一个简单的例子。创建一个工程,里面含有[/font][font=Times New Roman]A.cpp[/font][font=宋体]和[/font][font=Times New Roman]B.cpp[/font][font=宋体]两个简单的[/font][font=Times New Roman]C++[/font][font=宋体]源文件:[/font][/size]
[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]//A.cpp
[/font][/size]

[size=9pt][font=Times New Roman]int i;
[/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]void main()
[/font][/size]

[size=9pt][font=Times New Roman]{
[/font][/size]

[size=9pt][font=Times New Roman]}[b]
[/b][/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]//B.cpp
[/font][/size]

[size=9pt][font=Times New Roman]int i;
[/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3]       [/size][/font]
[size=3][font=宋体]这两个文件极为简单,在[/font][font=Times New Roman]A.cpp[/font][font=宋体]中我们定义了一个全局变量[/font][font=Times New Roman]i[/font][font=宋体],在[/font][font=Times New Roman]B[/font][font=宋体]中我们也定义了一个全局变量[/font][font=Times New Roman]i[/font][font=宋体]。[/font][/size]
[size=3][font=宋体]我们对[/font][font=Times New Roman]A[/font][font=宋体]和[/font][font=Times New Roman]B[/font][font=宋体]分别编译,都可以正常通过编译,但是进行链接的时候,却出现了错误,错误提示如下:[/font][/size]
[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]Linking...
[/font][/size]

[size=9pt][font=Times New Roman]B.obj : error LNK2005: "int i" (?i@@3HA) already defined in A.obj
[/font][/size]

[size=9pt][font=Times New Roman]Debug/A.exe : fatal error LNK1169: one or more multiply defined symbols found
[/font][/size]

[size=9pt][font=Times New Roman]Error executing link.exe.
[/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]A.exe - 2 error(s), 0 warning(s)
[/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[size=3][font=Times New Roman]       [/font][font=宋体]这就是说,在编译阶段,各个文件中定义的全局变量相互是透明的,编译[/font][font=Times New Roman]A[/font][font=宋体]时觉察不到[/font][font=Times New Roman]B[/font][font=宋体]中也定义了[/font][font=Times New Roman]i[/font][font=宋体],同样,编译[/font][font=Times New Roman]B[/font][font=宋体]时觉察不到[/font][font=Times New Roman]A[/font][font=宋体]中也定义了[/font][font=Times New Roman]i[/font][font=宋体]。[/font][/size]
[font=宋体][size=3]但是到了链接阶段,要将各个文件的内容“合为一体”,因此,如果某些文件中定义的全局变量名相同的话,在这个时候就会出现错误,也就是上面提示的重复定义的错误。[/size][/font]
[size=3][font=Times New Roman]       [/font][font=宋体]因此,各个文件中定义的全局变量名不可相同。[/font][/size]
[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3]       [/size][/font]
[size=3][font=Times New Roman]       [/font][font=宋体]在链接阶段,各个文件的内容(实际是编译产生的[/font][font=Times New Roman]obj[/font][font=宋体]文件)是被合并到一起的,因而,定义于某文件内的全局变量,在链接完成后,它的可见范围被扩大到了整个程序。[/font][/size]
[size=3][font=Times New Roman]       [/font][font=宋体]这样一来,按道理说,一个文件中定义的全局变量,可以在整个程序的任何地方被使用,举例说,如果[/font][font=Times New Roman]A[/font][font=宋体]文件中定义了某全局变量,那么[/font][font=Times New Roman]B[/font][font=宋体]文件中应可以该变量。修改我们的程序,加以验证:[/font][/size]
[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]//A.cpp
[/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]void main()
[/font][/size]

[size=9pt][font=Times New Roman]{
[/font][/size]

[size=9pt][font=Times New Roman]
i = 100; //[/font][/size][font=宋体][size=9pt]试图使用[/size][/font][size=9pt][font=Times New Roman]B[/font][/size][font=宋体][size=9pt]中定义的全局变量[/size][/font]


[size=9pt][font=Times New Roman]}[b]
[/b][/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]//B.cpp
[/font][/size]

[size=9pt][font=Times New Roman]int i;
[/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[size=3][font=Times New Roman]       [/font][font=宋体]编译结果如下:[/font][/size]
[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3]       [/size][/font]
[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]Compiling...
[/font][/size]

[size=9pt][font=Times New Roman]A.cpp
[/font][/size]

[size=9pt][font=Times New Roman]C:\Documents and Settings\wangjian\[/font][/size][font=宋体][size=9pt]桌面[/size][/font][size=9pt][font=Times New Roman]\try extern\A.cpp(5) : error C2065: 'i' : undeclared identifier
[/font][/size]

[size=9pt][font=Times New Roman]Error executing cl.exe.
[/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]A.obj - 1 error(s), 0 warning(s)
[/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[size=3][font=Times New Roman]       [/font][font=宋体]编译错误。[/font][/size]
[size=3][font=Times New Roman]       [/font][font=宋体]其实出现这个错误是意料之中的,因为:文件中定义的全局变量的可见性扩展到整个程序是在链接完成之后,而在编译阶段,他们的可见性仍局限于各自的文件。[/font][/size]
[size=3][font=Times New Roman]       [/font][font=宋体]编译器的目光不够长远,编译器没有能够意识到,某个变量符号虽然不是本文件定义的,但是它可能是在其它的文件中定义的。[/font][/size]
[font=Times New Roman][size=3]       [/size][/font]
[size=3][font=Times New Roman]       [/font][font=宋体]虽然编译器不够远见,但是我们可以给它提示,帮助它来解决上面出现的问题。这就是[/font][font=Times New Roman]extern[/font][font=宋体]的作用了。[/font][/size]
[size=3][font=Times New Roman]
extern[/font][font=宋体]的原理很简单,就是告诉编译器:“你现在编译的文件中,有一个标识符虽然没有在本文件中定义,但是它是在别的文件中定义的全局变量,你要放行!”[/font][/size]
[size=3][font=Times New Roman]       [/font][font=宋体]我们为上面的错误程序加上[/font][font=Times New Roman]extern[/font][font=宋体]关键字:[/font][/size]
[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]//A.cpp
[/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[b][size=9pt][font=Times New Roman]extern int i;
[/font][/size][/b]

[size=9pt][font=Times New Roman]void main()
[/font][/size]

[size=9pt][font=Times New Roman]{
[/font][/size]

[size=9pt][font=Times New Roman]
i = 100; //[/font][/size][font=宋体][size=9pt]试图使用[/size][/font][size=9pt][font=Times New Roman]B[/font][/size][font=宋体][size=9pt]中定义的全局变量[/size][/font]


[size=9pt][font=Times New Roman]}[b]
[/b][/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]//B.cpp
[/font][/size]

[size=9pt][font=Times New Roman]int i;
[/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[size=3][font=Times New Roman]       [/font][font=宋体]顺利通过编译,链接。[/font][/size]
[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[b][font=Times New Roman][size=3]2、[/size]
[/font][/b][size=3][b][font=宋体]在[/font][font=Times New Roman]C++[/font][/b][b][font=宋体]文件中调用[/font][font=Times New Roman]C[/font][/b][b][font=宋体]方式编译的函数[/font]
[/b][/size]

[font=Times New Roman][size=3][/size][/font]


[size=3][font=Times New Roman]C[/font][font=宋体]方式编译和[/font][font=Times New Roman]C++[/font][font=宋体]方式编译[/font][/size]
[size=3][font=宋体]相对于[/font][font=Times New Roman]C[/font][font=宋体],[/font][font=Times New Roman]C++[/font][font=宋体]中新增了诸如重载等新特性,对于他们的编译,必然有一些重要的区别。[/font][/size]
[size=3][font=宋体]我们将下面的小程序分别按[/font][font=Times New Roman]C[/font][font=宋体]和[/font][font=Times New Roman]C++[/font][font=宋体]方式编译,来探讨两种编译方式的区别。[/font][/size]
[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]int i;
[/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]int func(int t)
[/font][/size]

[size=9pt][font=Times New Roman]{
[/font][/size]

[size=9pt][font=Times New Roman]
return 0;
[/font][/size]

[size=9pt][font=Times New Roman]}
[/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]void main()
[/font][/size]

[size=9pt][font=Times New Roman]{
[/font][/size]

[size=9pt][font=Times New Roman]}[b]
[/b][/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[b][font=Times New Roman][size=3][/size][/font]
[/b]

[size=3][b][font=Times New Roman]       [/font][/b][font=宋体]以[/font][font=Times New Roman]C[/font][font=宋体]方式编译的结果:[/font][/size]
[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]COMM
_i
:
DWORD
[/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]PUBLIC
_func
[/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]PUBLIC
_main
[/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[size=3][font=Times New Roman]       [/font][font=宋体]以[/font][font=Times New Roman]C++[/font][font=宋体]方式编译的结果:[/font][/size]
[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]PUBLIC
?i@@3HA
; i
[/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]PUBLIC
?func@@YAHH@Z
; func
[/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]PUBLIC
_main
[/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[b][font=Times New Roman][size=3][/size][/font]
[/b]

[b][font=Times New Roman][size=3][/size][/font]
[/b]

[b][font=Times New Roman][size=3][/size][/font]
[/b]

[b][font=Times New Roman][size=3][/size][/font]
[/b]

[size=3][b][font=Times New Roman]       [/font][/b][font=宋体]可见,[/font][font=Times New Roman]C[/font][font=宋体]方式编译下,变量名和函数名之前被统一加上了一个下划线,而[/font][font=Times New Roman]C++[/font][font=宋体]编译后的结果却复杂的多,[/font][font=Times New Roman]i[/font][font=宋体]变成了[/font][font=Times New Roman]?i@@3HA[/font][font=宋体],[/font][font=Times New Roman]func[/font][font=宋体]变成了[/font][font=Times New Roman]?func@@YAHH@Z[/font][font=宋体]。[/font][font=Times New Roman]C++[/font][font=宋体]中的这种看似复杂的命名规则是为[/font][font=Times New Roman]C++[/font][font=宋体]中的函数重载,参数检查等特性服务的。[/font]
[/size][b]
[/b]

CPP 2008-10-1 20:04

[size=3][font=宋体]多文件程序中的函数调用[/font]
[/size]

[size=3][font=Times New Roman]       [/font][font=宋体]一般情况下,工程中的文件都是[/font][font=Times New Roman]CPP[/font][font=宋体]文件(以及头文件)。如下面的程序仅包含两个文件:[/font][font=Times New Roman]A.CPP[/font][font=宋体]和[/font][font=Times New Roman]B.CPP[/font][font=宋体]:[/font]
[/size]

[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]//A.CPP
[/font][/size]

[size=9pt][font=Times New Roman]void func();
[/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]void main()
[/font][/size]

[size=9pt][font=Times New Roman]{
[/font][/size]

[size=9pt][font=Times New Roman]
func();
[/font][/size]

[size=9pt][font=Times New Roman]}
[/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]





[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]//B.CPP
[/font][/size]

[size=9pt][font=Times New Roman]void func()
[/font][/size]

[size=9pt][font=Times New Roman]{
[/font][/size]

[size=9pt][font=Times New Roman]}
[/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[size=3][font=Times New Roman]       [/font][font=宋体]程序的结构是这样的:在文件[/font][font=Times New Roman]B.CPP[/font][font=宋体]中定义了一个函数[/font][font=Times New Roman]void func()[/font][font=宋体],[/font][font=Times New Roman]main[/font][font=宋体]函数位于文件[/font][font=Times New Roman]A.CPP[/font][font=宋体],在[/font][font=Times New Roman]main[/font][font=宋体]函数中调用了[/font][font=Times New Roman]B[/font][font=宋体]中定义的函数[/font][font=Times New Roman]func()[/font][font=宋体]。[/font][/size]
[size=3][font=Times New Roman]       [/font][font=宋体]要在[/font][font=Times New Roman]A[/font][font=宋体]中调用[/font][font=Times New Roman]B[/font][font=宋体]中定义的函数,必须要加上该函数的声明。如本例中的[/font][font=Times New Roman]void func();[/font][font=宋体]就是对函数[/font][font=Times New Roman]func()[/font][font=宋体]的声明。[/font][/size]
[size=3][font=宋体]如果没有声明的话,编译[/font][font=Times New Roman]A.CPP[/font][font=宋体]时就会出错。因为编译器的目光只局限于被编译文件,必须通过加入函数声明来告诉编译器:“某个函数是定义在其它的文件中的,你要放行!”,这一点跟用[/font][font=Times New Roman]extern[/font][font=宋体]来声明外部全局变量是一个道理。[/font][/size]
[size=3][font=Times New Roman]       [/font][font=宋体]需要注意的是,一般的程序都是通过包含头文件来完成函数的声明。拿本例来说,一般是创建一个头文件[/font][font=Times New Roman]B.H[/font][font=宋体],在头文件中加入声明语句[/font][font=Times New Roman]void func(); [/font][font=宋体]并且在[/font][font=Times New Roman]A.CPP[/font][font=宋体]中加入包含语句:[/font][font=Times New Roman]#include “B.H”[/font][font=宋体]。[/font]
[/size]

[size=3][font=Times New Roman]       [/font][font=宋体]在[/font][font=Times New Roman]C++[/font][font=宋体]程序中,头文件的功能从函数声明被扩展为类的定义。[/font]
[/size]

[font=Times New Roman][size=3][/size][/font]


[font=宋体][size=3]不同编译方式下的函数调用[/size][/font]
[size=3][font=Times New Roman]       [/font][font=宋体]如果在工程中,不仅有[/font][font=Times New Roman]CPP[/font][font=宋体]文件,还有以[/font][font=Times New Roman]C[/font][font=宋体]方式编译的[/font][font=Times New Roman]C[/font][font=宋体]文件,函数调用就会有一些微妙之处。我们将[/font][font=Times New Roman]B.CPP[/font][font=宋体]改作[/font][font=Times New Roman]B.C[/font][font=宋体]:[/font][/size]
[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]//A.CPP
[/font][/size]

[size=9pt][font=Times New Roman]void func();
[/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]void main()
[/font][/size]

[size=9pt][font=Times New Roman]{
[/font][/size]

[size=9pt][font=Times New Roman]
func();
[/font][/size]

[size=9pt][font=Times New Roman]}
[/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]//B.C
[/font][/size]

[size=9pt][font=Times New Roman]void func()
[/font][/size]

[size=9pt][font=Times New Roman]{
[/font][/size]

[size=9pt][font=Times New Roman]}
[/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[size=3][font=Times New Roman]       [/font][font=宋体]对[/font][font=Times New Roman]A.CPP[/font][font=宋体]和[/font][font=Times New Roman]B.C[/font][font=宋体]分别编译,都没有问题,但是链接时出现错误。[/font][/size]
[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]Linking...
[/font][/size]

[size=9pt][font=Times New Roman]A.obj : error LNK2001: unresolved external symbol "void __cdecl func(void)" (?func@@YAXXZ)
[/font][/size]

[size=9pt][font=Times New Roman]Debug/A.exe : fatal error LNK1120: 1 unresolved externals
[/font][/size]

[size=9pt][font=Times New Roman]Error executing link.exe.
[/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]A.exe - 2 error(s), 0 warning(s)
[/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=宋体][size=3]原因就在于不同的编译方式产生的冲突。[/size][/font]
[font=Times New Roman][size=3][/size][/font]


[size=3][font=Times New Roman]       [/font][font=宋体]对于文件[/font][font=Times New Roman]A[/font][font=宋体],是按照[/font][font=Times New Roman]C++[/font][font=宋体]的方式进行编译的,其中的[/font][font=Times New Roman]func()[/font][font=宋体]调用被编译成了[/font][/size]
[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]call
?func1@@YAXXZ
[/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[size=3][font=宋体]如果[/font][font=Times New Roman]B[/font][font=宋体]文件也是按照[/font][font=Times New Roman]C++[/font][font=宋体]方式编译的,那么[/font][font=Times New Roman]B[/font][font=宋体]中的[/font][font=Times New Roman]func[/font][font=宋体]函数名也会被编译器改成[/font][font=Times New Roman]?func1@@YAXXZ[/font][font=宋体],这样的话,就没有任何问题。[/font][/size]
[size=3][font=Times New Roman]       [/font][font=宋体]但是现在对[/font][font=Times New Roman]B[/font][font=宋体]文件,是按照[/font][font=Times New Roman]C[/font][font=宋体]方式编译的,[/font][font=Times New Roman]B[/font][font=宋体]中的[/font][font=Times New Roman]func[/font][font=宋体]函数名被改成了[/font][font=Times New Roman]_func[/font][font=宋体],这样一来,[/font][font=Times New Roman]A[/font][font=宋体]中的[/font][font=Times New Roman]call ?func1@@YAXXZ[/font][font=宋体]这个函数调用就没有了着落,因为在链接器看来,[/font][font=Times New Roman]B[/font][font=宋体]文件中没有名为[/font][font=Times New Roman]?func1@@YAXXZ[/font][font=宋体]的函数。[/font][/size]
[size=3][font=Times New Roman]       [/font][font=宋体]事实是,我们编程者知道,[/font][font=Times New Roman]B[/font][font=宋体]文件中有[/font][font=Times New Roman]A[/font][font=宋体]中调用的[/font][font=Times New Roman]func[/font][font=宋体]函数的定义,只不过它是按照[/font][font=Times New Roman]C[/font][font=宋体]方式编译的,故它的名字被改成了[/font][font=Times New Roman]_func[/font][font=宋体]。因而,我们需要通过某种方式告诉编译器:“[/font][font=Times New Roman]B[/font][font=宋体]中定义的函数[/font][font=Times New Roman]func()[/font][font=宋体]经编译后命名成了[/font][font=Times New Roman]_func[/font][font=宋体],而不是[/font][font=Times New Roman]?func1@@YAXXZ[/font][font=宋体],你必须通过[/font][font=Times New Roman]call _func[/font][font=宋体]来调用它,而不是[/font][font=Times New Roman]call ?func1@@YAXXZ[/font][font=宋体]。”简单的说,就是告诉编译器,调用的[/font][font=Times New Roman]func()[/font][font=宋体]函数是以[/font][font=Times New Roman]C[/font][font=宋体]方式编译的,[/font][font=Times New Roman]fun();[/font][font=宋体]语句必须被编译成[/font][font=Times New Roman]call _func;[/font][font=宋体]而不是[/font][font=Times New Roman]call ?func1@@YAXXZ[/font][font=宋体]。[/font][/size]
[font=Times New Roman][size=3]       [/size][/font]
[size=3][font=Times New Roman]       [/font][font=宋体]我们可以通过[/font][font=Times New Roman]extern[/font][font=宋体]关键字,来帮助编译器解决上面提到的问题。[/font][/size]
[size=3][font=Times New Roman]       [/font][font=宋体]对于本例,只需将[/font][font=Times New Roman]A.CPP[/font][font=宋体]改成如下即可:[/font][/size]
[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]//A.CPP [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[b][size=9pt][font=Times New Roman]extern "C" [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size][/b]

[b][size=9pt][font=Times New Roman]{ [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size][/b]

[b][size=9pt][font=Times New Roman]
void func(); [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size][/b]

[b][size=9pt][font=Times New Roman]} [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size][/b]

[size=9pt][font=Times New Roman]void main() [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman]{ [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman]
func(); [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman]} [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3]       [/size][/font]
[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[size=3][font=Times New Roman]       [/font][font=宋体]察看汇编代码,发现此时的[/font][font=Times New Roman]func();[/font][font=宋体]语句被编译成了[/font][font=Times New Roman]call _func[/font][font=宋体]。[/font][/size]
[b][font=Times New Roman][size=3]3、[/size]
[/font][/b][b][size=3][font=宋体]补充[/font]
[/size][/b]

[size=3][font=宋体]同[/font][font=Times New Roman]2[/font][font=宋体]一样,仍然是[/font][font=Times New Roman]C[/font][font=宋体],[/font][font=Times New Roman]C++[/font][font=宋体]混合编程的情形,考虑下面的程序:[/font][/size]
[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]//A.CPP [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]extern int i; [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]void main() [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman]{ [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman]
i = 100; [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman]} [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]//B.C [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman]int i; [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[size=3][font=Times New Roman]       [/font][font=宋体]程序很简单:在文件[/font][font=Times New Roman]B.C[/font][font=宋体]中定义了一个全局变量[/font][font=Times New Roman]i[/font][font=宋体],在[/font][font=Times New Roman]A.CPP[/font][font=宋体]中使用了这个全局变量。[/font][/size]
[size=3][font=Times New Roman]       [/font][font=宋体]编译没有问题,链接时却出现错误:[/font][/size]
[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]Linking... [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman]A.obj : error LNK2001: unresolved external symbol "int i" (?i@@3HA) [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman]Debug/A.exe : fatal error LNK1120: 1 unresolved externals [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman]Error executing link.exe. [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]A.exe - 2 error(s), 0 warning(s) [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3]       [/size][/font]
[size=3][font=Times New Roman]

[/font][font=宋体]这是因为,在[/font][font=Times New Roman]C[/font][font=宋体]方式编译下,[/font][font=Times New Roman]i[/font][font=宋体]被重命名为[/font][font=Times New Roman]_i[/font][font=宋体],而在[/font][font=Times New Roman]C++[/font][font=宋体]方式下,[/font][font=Times New Roman]i[/font][font=宋体]会被重命名为[/font][font=Times New Roman]?i@@3HA[/font][font=宋体]。[/font]
[/size]

[size=3][font=宋体]因而,我们只用[/font][font=Times New Roman]extern int i;[/font][font=宋体]来声明还不够,必须告诉编译器,全局变量[/font][font=Times New Roman]i[/font][font=宋体]是以[/font][font=Times New Roman]C[/font][font=宋体]方式编译的,[/font]
[/size]

[size=3][font=宋体]它会被重命名为[/font][font=Times New Roman]_i[/font][font=宋体],而不是[/font][font=Times New Roman]?i@@3HA[/font][font=宋体]。[/font]
[/size]

[font=Times New Roman][size=3][/size][/font]


[size=3][font=Times New Roman]       [/font][font=宋体]我们修改[/font][font=Times New Roman]A.CPP[/font][font=宋体],如下:[/font]
[/size]

[table=495,rgb(224,224,224)][tr][td][size=9pt][font=Times New Roman]//A.CPP [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[b][size=9pt][font=Times New Roman]extern "C" [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size][/b]

[b][size=9pt][font=Times New Roman]{ [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size][/b]

[b][size=9pt][font=Times New Roman]
int i; [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size][/b]

[b][size=9pt][font=Times New Roman]} [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size][/b]

[size=9pt][font=Times New Roman]void main() [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman]{ [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman][/font]
[/size]

[size=9pt][font=Times New Roman]
i = 100; [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[size=9pt][font=Times New Roman]} [/font][font=Times New Roman][/font]
[font=Times New Roman][/font][/size]

[/td][/tr][/table][font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[font=Times New Roman][size=3][/size][/font]


[size=3][font=Times New Roman]       [/font][font=宋体]程序正常通过编译和链接。[/font]
[/size]

[size=3][font=Times New Roman]       [/font][font=宋体]我们察看一下汇编代码,发现语句[/font][font=Times New Roman]i = 100;[/font][font=宋体]被编译成了[/font][font=Times New Roman]mov
DWORD PTR _i, 100[/font][font=宋体]。[/font][/size]
页: [1]
查看完整版本: 解析“extern”