我知道C中的全局变量有时有extern关键字。什么是extern变量?申报是什么样的?它的范围是什么?

这与跨源文件共享变量有关,但这究竟是如何工作的呢?我在哪里使用extern?


当前回答

我喜欢把extern变量看作是你对编译器做出的承诺。

当遇到一个extern时,编译器只能找出它的类型,而不能找出它“居住”的位置,因此它不能解析引用。

你告诉它:“相信我。在链接时,这个引用将是可解析的。”

其他回答

GCC ELF Linux实现

其他答案已经涵盖了语言使用方面的观点,所以现在让我们看看它是如何在这个实现中实现的。

c

#include <stdio.h>

int not_extern_int = 1;
extern int extern_int;

void main() {
    printf("%d\n", not_extern_int);
    printf("%d\n", extern_int);
}

编译和反编译:

gcc -c main.c
readelf -s main.o

输出包含:

Num:    Value          Size Type    Bind   Vis      Ndx Name
 9: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    3 not_extern_int
12: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND extern_int

System V ABI Update ELF规范“符号表”章节解释:

这个节表索引表示该符号未定义。当链接编辑器将这个目标文件与另一个定义指定符号的文件结合在一起时,这个文件对符号的引用将被链接到实际的定义。

这基本上是C标准赋予extern变量的行为。

从现在开始,制作最终程序是链接器的工作,但是extern信息已经从源代码中提取到目标文件中。

在GCC 4.8上测试。

c++ 17内联变量

在c++ 17中,你可能想要使用内联变量而不是extern变量,因为它们使用简单(可以在头文件中定义一次)并且更强大(支持constexpr)。参见:“const static”在C和c++中是什么意思?

Extern是用于声明变量本身驻留在另一个翻译单元中的关键字。

因此,您可以决定在一个转换单元中使用一个变量,然后从另一个转换单元访问它,然后在第二个转换单元中将其声明为extern,符号将由链接器解析。

如果不将其声明为extern,则会得到两个名称相同但完全不相关的变量,并且变量的多个定义存在错误。

Extern关键字与变量一起使用,以将其标识为全局变量。

它还表示可以使用使用extern声明的变量 关键字在任何文件中,尽管它在其他文件中声明/定义。

extern keyword before a symbol (a var or function) tells the linker that it(the source file) uses an external symbol. This can be seen by running nm -a on such an object file (.o) which uses or assigns a value to a extern var (remember to declare a extern symbol on top like this extern int x or still better, use a header file with extern before vars and functions can be without extern; then in main assign a value to it like this x=5;), i find undefined bss info (letter B written) against such an extern var(symbol). This means x is still unresolved and will be resolved when ld is run (during link-time).

why always use extern in headers? If i don't use extern, just declare int x, the declaration becomes sort-of strong and without extern, and this redifines the same variable in every source that includes the header, effectively shadowing the original variable. therefore with just int x in a.h header, I redefine a new global variable x in every source that include this a.h. This var in the source, this without-extern var decl in headers shadows(it doesn't shadow exactly, it's redifining a global variable x in every source code that includes the header with just int x, without extern, when i include such header and try to compile .o from such files, every .o has its own definition of this global variable x which was included in the header without extern, and at the time of linking, I get the error multiple definition of variable or symbol x) an important variable defined somewhere of somewhere else in the source files. Important! it is necessary to use extern before vars in headers. Functions are already extern by-default.

简而言之,extern意味着变量是在其他模块中定义的,它的地址在链接时是已知的。编译器不会在当前模块中保留内存,并且知道变量类型。要理解extern,至少要有很少的汇编经验。