在头文件中定义变量- C
在C语言中,头文件(header files)对于编译器来说没有任何特殊的语义,它们只是会被预处理器内联展开的文本。这意味着你在头文件中定义的变量将会被链接器看到三次。为了避免混淆,链接器不知道这三个值中哪一个是正确的。即使它们这一次碰巧有相同的值,链接器还是愚蠢的,并不知道这一点。
如果你只是有一个"int num;",这是一个特殊情况,变量会被分配为common而不是data,链接器知道在最终的链接阶段统一common。一般来说,我会说使用common是不好的形式,头文件应该只有"extern int foo;",而变量本身只在一个链接单元中定义。
原因:
在C语言中,头文件通过预处理器展开后会被多次看到,这会导致链接器不知道变量的定义到底是哪一个正确的值。
解决方法:
避免在头文件中定义变量,应该将变量的声明放在头文件中,而将变量的定义放在一个链接单元中。这样可以避免链接器对变量定义的混淆。
示例代码:
// header.h
extern int num; // 变量的声明
// source1.c
#include "header.h"
int num = 10; // 变量的定义
// source2.c
#include "header.h"
int num = 20; // 变量的定义
这样,通过将变量的声明放在头文件中,变量的定义放在一个链接单元中,就可以避免链接器对变量定义的混淆,确保只有一个正确的值被链接到最终的程序中。
在C语言中,可以多次声明全局变量,但是只能在一个翻译单元中初始化。因此在file.h
文件中,可以写下
extern int num;
,然后在file.c
文件中写下
int num = 4;
。需要确保只在一个C文件中包含最后一行代码,其他文件将使用该一次出现的值。
如果在头文件中没有将变量声明为extern关键字,会发生什么呢?这是定义全局变量的方式。即使没有使用"extern"关键字,这种方式似乎也可以正常工作。那么到底会发生什么呢?
"extern"关键字声明了一个变量或者函数,并指定它具有外部链接(其名称可以在其他文件中可见)。当修改一个变量时,extern指定该变量具有静态持续时间(在程序开始时分配,在程序结束时释放)。变量或函数可以在另一个源文件中定义,或者稍后在同一文件中定义。默认情况下,文件范围的变量和函数声明是外部的。
所以,如果在其他两个源文件中写下"int num"而不初始化它,这样做也是完全可以的吗?这取决于你想要实现什么。这就像在定义函数之前声明函数一样。
如果你写下int num
,你是告诉编译器“请保留一些内存并将其与给定的名称关联起来”。如果你写下extern int num
,那么你是告诉编译器“将会有某人在该名称下保留内存,可以自由使用它”。因此,如果没有使用extern关键字,将会有多个具有相同名称的内存位置,导致链接问题。