C中全局变量的可见性/作用域是什么?



我有两个。c文件:A1.c和A2.c

A1.c如下:

int i=0;
void main()
{}

A2.c如下:

int i=0;
void func()
{}

它编译得很好,但当我试图链接这两个。o文件时,有一个"I的多个定义"错误。我理解i在这里是一个全局变量,但它不需要在其他文件中使用extern关键字吗?在我的项目中,我没有使用extern。为什么会出现错误呢?

在编译时,编译器将每个全局符号导出为强符号或弱符号,汇编器将这些信息隐式地编码在可重定位对象文件的符号表中。函数和初始化的全局变量获得强符号。未初始化的全局变量得到弱符号。

考虑到强弱符号的概念,Unix连接器使用以下规则来处理多重定义的符号:

规则1:不允许使用多个强符号。
规则2:给定一个强符号和多个弱符号,选择强符号。
规则3:给定多个弱符号,选择其中任意一个

代码,

int i=0; // Strong Symbol
void main() {}

A2.c如下:

int i=0; // Strong symbol
void func() {}

根据规则1这是不允许的。

查看更多详细信息:http://www.geeksforgeeks.org/how-linkers-resolve-multiply-defined-global-symbols/

长话短说,像

extern int i;

是一个声明,而语句

int i=0;

定义

在C语言中,你可以在一个程序中多次声明一个变量,但是你只能定义它一次。第一个语句向A2表示变量i的定义在另一个文件中。首先,我不明白你为什么对使用"extern"这么担心。

在C中,只要另一个编译单元看到全局变量存在,就可以从另一个编译单元访问全局变量,通过将其声明为extern。链接器使作业将外部声明和另一个。c中的定义链接起来。

如果你希望它只对你正在编译的。c可见,你必须指定它为static

static int i = 0;

当然,它在链接上失败了:它试图组合两个对象文件,这两个文件在两个不同的内存位置引用一个对象。

在这种情况下,变量的真正定义在所有源代码中必须是唯一的,并且对该变量的所有其他引用必须通过使用external关键字(如您所见)来完成。

编译器不会报错,因为它不知道你的两个文件的关系,只有链接器需要弄清楚。

最新更新