外部变量VS标头声明

时间:2019-12-25 19:18:41

标签: c

何时使用extern,何时使用标头共享变量?假设以下内容:

test1.h

int a;

test1.c

#include "test1.h"

a = 5

VS

test1.h

extern int a;

test1.c

#include "test1.h"

int a = 5

我还看到人们在头文件中使用extern来定义全局变量,但是我可以 通过省略extern并仅使用头文件来获得相同的输出。它可以编译并正常运行。

3 个答案:

答案 0 :(得分:0)

使用

int a;

您有一个tentative definition。如果在当前translation unit中未找到其他定义,则为定义,否则为声明。

使用

extern int a;

您只声明变量a,告诉编译器它将在程序的某个位置找到,无论是在当前翻译单元中还是在另一个翻译单元中。


请注意

extern int a = 5;

是一个实际的定义,就像普通的

int a;

不同之处在于extern int a = 5;包含变量的初始化程序。


您不能在全局(非功能)范围内使用通用语句。其中包括诸如

a = 5;  // Invalid if not inside a function

但是以下内容有效:

int a;      // Tentative definition
...
int a = 5;  // Actual definition, the above becomes a declaration

最后,在全局(非功能)范围内定义的所有变量都将具有外部链接,无论是否带有extern关键字:

int a = 5;         // Definition with external linkage
extern int b = 5;  // Definition with external linkage'

来自this storage duration reference

  

如果未提供存储类说明符,则默认值为:

     
      
  • 所有功能都为外部
  •   
  • 外部文件范围内的对象
  •   
  • 自动用于块范围内的对象
  •   

[我对相关内容的强调]

答案 1 :(得分:0)

如果在临时定义的范围内将标头包含在多个翻译单元中,则第一种方法可能会导致链接器错误

int a;

在某些翻译单元中没有外部定义。

所有包含标头的翻译单元都将对具有外部链接的变量a具有自己的暂定定义,链接器将确定歧义。

考虑到该记录

a = 5;

不是具有暂定定义的变量的定义。这只是一项任务。

因此,与第一种方法相比,第二种方法更可取。

当标头仅包含在用于小程序的一个翻译单元中时,可以使用第一种方法。

答案 2 :(得分:0)

当您有两个以上.c文件时使用

extern,并且在生成可执行文件时由链接器使用y。猜想:

test1.h

   extern int a;

test1.c

     #include "test1.h"

      Int a;
      void somemethod() {
      }

test2.c

   #include "test1.h"

    void otherMethod() {
          a=5;
     }
在编译方式中,

由于包含test1.h,test2.c具有对变量“ a”的外部引用。编译器将此引用留作待处理,以供链接器解决。在链接器阶段,然后在test1.c中找到“ a”,然后链接器确定test2.c中的“ a”是对test1.c中定义的“ a”的引用。注意“ a”是全局的。

如果在test1.h中删除extern,则在构建时会出现多个定义错误,因为test1.c和test2.c具有相同的变量“ a”。因为两个都包含test1.h。我希望了解我。我的英语是这样。或者可以有人描述得更好。