我知道C中的全局变量有时有extern关键字。什么是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

其他回答

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

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

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

我使用了一个非常简短的解决方案,允许头文件包含对象的extern引用或实际实现。实际包含该对象的文件只是#define GLOBAL_FOO_IMPLEMENTATION。然后,当我向这个文件添加一个新对象时,它也会显示在那个文件中,而不需要我复制和粘贴定义。

我在多个文件中使用这种模式。因此,为了保持内容尽可能自包含,我只是在每个头文件中重用单个GLOBAL宏。我的标题是这样的:

//file foo_globals.h
#pragma once  
#include "foo.h"  //contains definition of foo

#ifdef GLOBAL  
#undef GLOBAL  
#endif  

#ifdef GLOBAL_FOO_IMPLEMENTATION  
#define GLOBAL  
#else  
#define GLOBAL extern  
#endif  

GLOBAL Foo foo1;  
GLOBAL Foo foo2;


//file main.cpp
#define GLOBAL_FOO_IMPLEMENTATION
#include "foo_globals.h"

//file uses_extern_foo.cpp
#include "foo_globals.h

走读生 允许程序的一个模块访问程序的另一个模块中声明的全局变量或函数。 通常在头文件中声明extern变量。

如果你不想让一个程序访问你的变量或函数,你可以使用static,它告诉编译器这个变量或函数不能在这个模块之外使用。

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

对于xc8,必须小心声明变量 在每个文件中都是相同的类型, 在一个文件中声明int型,在另一个文件中声明char型。 这可能会导致变量的破坏。

这个问题在大约15年前的一个微芯片论坛上得到了优雅的解决 /*参见“http:www.htsoft.com”/ /“论坛/ / showflat.php /猫/ 0 /数字/ 18766 / / /页面/ 0 # 18766”

但这种联系似乎不再起作用了……

所以我很快就会解释一下; 创建一个名为global.h的文件。

在其中声明以下内容

#ifdef MAIN_C
#define GLOBAL
 /* #warning COMPILING MAIN.C */
#else
#define GLOBAL extern
#endif
GLOBAL unsigned char testing_mode; // example var used in several C files

现在在文件main.c中

#define MAIN_C 1
#include "global.h"
#undef MAIN_C

这意味着在main.c中变量将被声明为unsigned char。

现在在其他文件中简单地包括global.h将 将其声明为该文件的extern。

extern unsigned char testing_mode;

但是它将被正确地声明为unsigned char。

旧的论坛帖子可能解释得更清楚一点。 但在使用编译器时,这是一个真正的潜在问题 这允许您在一个文件中声明一个变量,然后在另一个文件中将其声明为不同的类型。这些问题与 也就是说,如果你在另一个文件中将testing_mode声明为int类型 它会认为它是一个16位的变量,并覆盖ram的其他部分,可能会破坏另一个变量。很难调试!