我知道C中的全局变量有时有extern关键字。什么是extern变量?申报是什么样的?它的范围是什么?
这与跨源文件共享变量有关,但这究竟是如何工作的呢?我在哪里使用extern?
我知道C中的全局变量有时有extern关键字。什么是extern变量?申报是什么样的?它的范围是什么?
这与跨源文件共享变量有关,但这究竟是如何工作的呢?我在哪里使用extern?
当前回答
Extern仅仅意味着变量在其他地方定义(例如,在另一个文件中)。
其他回答
declare | define | initialize |
----------------------------------
extern int a; yes no no
-------------
int a = 2019; yes yes yes
-------------
int a; yes yes no
-------------
声明不会分配内存(必须为分配内存而定义变量),但定义会。 这只是对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变量是在另一个翻译单元中定义的变量的声明(感谢sbi的更正)。这意味着变量的存储空间被分配到另一个文件中。
假设您有两个.c文件test1.c和test2.c。如果你定义一个全局变量int test1_var;在test1.c中你想访问test2.c中的这个变量你必须使用extern int test1_var;在test2.c。
完整的示例:
$ cat test1.c
int test1_var = 5;
$ cat test2.c
#include <stdio.h>
extern int test1_var;
int main(void) {
printf("test1_var = %d\n", test1_var);
return 0;
}
$ gcc test1.c test2.c -o test
$ ./test
test1_var = 5