声明外部变量
现代编译器一般采用按文件编译的方式,因此在编译时,各个文件中定义的全局变量是互相透明的,也就是说,在编译时,全局变量的可见域限制在文件内部。下面举一个简单的例子。创建一个工程,里面含有A.cpp和B.cpp两个简单的C++源文件:
//A.cpp inti; voidmain() { }
//B.cpp int i;
这两个文件极为简单,在A.cpp中定义了一个全局变量i,在B中也定义了一个全局变量i。对A和B分别编译,都可以正常通过编译,但是进行链接的时候,却出现了错误,错误提示如下:
Linking... B.obj:errorLNK2005:"inti"(?i@@3HA)alreadydefinedinA.obj Debug/A.exe:fatalerrorLNK1169:oneormoremultiplydefinedsymbolsfound Errorexecutinglink.exe. A.exe - 2 error(s), 0 warning(s)
这就是说,在编译阶段,各个文件中定义的全局变量相互是透明的,编译A时觉察不到B中也定义了i,同样,编译B时觉察不到A中也定义了i。但是在链接阶段,要将各个文件的内容“合为一体”,因此,如果某些文件中定义的全局变量名相同的话,在链接阶段就会报重复定义(oneormoremultiplydefinedsymbols)的错误。
因此,各个文件中定义的全局变量名不可相同。
在链接阶段,编译产生的obj文件合并了A、B两文件的内容,这也是出现int i重复定义错误的原因。
举个例子
一个文件中定义的全局变量,可以在整个程序的任何地方被使用,举例说,如果A文件中定义了某全局变量,那么B文件中也可以使用该变量。修改我们的程序,加以验证:
//A.cpp voidmain() { i=100; //试图使用B中定义的全局变量 }
//B.cpp int i;
出现如下意料之中的编译错误,未定义int i错误(undeclaredidentifierError),因为在链接之前A、B文件中的变量是彼此不可见的。
Compiling... A.cpp C:/Documents and Settings/wangjian/桌面/try extern/A.cpp(5) : error C2065: 'i' : undeclared identifier Errorexecutingcl.exe. A.obj-1error(s),0warning(s)
编译器没有能够意识到,某个变量符号虽然不是本文件定义的,但是它可能是在其它的文件中定义的,为了避免错误的发生extern派上用场了。为上面的错误程序加上extern关键字后,顺利通过编译,链接,代码如下:
//A.cpp externinti; voidmain() { i=100;//试图使用B中定义的全局变量 }
//B.cpp int i;
在C++文件中调用C方式编译的函数
相对于C,C++中新增了诸如重载等新特性,它们的编译有一些重要区别。将下面的小程序分别按C和C++方式编译,来探讨两种编译方式的区别。
inti; intfunc(intt) { return0; } voidmain() { }
以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文件,还有以C方式编译的C文件,函数调用就会有一些微妙之处。有如下CPP文件A.CPP和C文件B.C两个文件。
//A.CPP voidfunc(); voidmain() { func(); }
//B.C void func() { }
对A.CPP和B.C分别编译,都没有问题,但是链接时出现错误,原因就是C和CPP不同的编译方式产生的冲突。比如在上文中提到,C方式编译下,变量名和函数名之前被统一加上了一个下划线,而C++编译后的结果却复杂的多,i变成了?i@@ 3HA。
Linking... A.obj:errorLNK2001:unresolvedexternalsymbol"void__cdeclfunc(void)"(?func@@YAXXZ) Debug/A.exe:fatalerrorLNK1120:1unresolvedexternals Errorexecutinglink.exe. A.exe - 2 error(s), 0 warning(s)
此时,可以通过extern关键字,来帮助编译器解决上面提到的问题。对于本例,只需将A.CPP改成如下代码即可:
//A.CPP extern "C" { void func(); //引入C语言方式编译的函数或变量 } void main() { func(); }
审核编辑:汤梓红
-
函数
+关注
关注
3文章
4328浏览量
62575 -
C++
+关注
关注
22文章
2108浏览量
73623 -
编译器
+关注
关注
1文章
1624浏览量
49109 -
extern
+关注
关注
0文章
7浏览量
2951
原文标题:C/C++语言中extern的用法
文章出处:【微信号:单片机与嵌入式,微信公众号:单片机与嵌入式】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论