繁体   English   中英

extern类说明符

[英]The extern class specifier

如果我有这样的外部变量:

int a;

是的,声明等于:

extern int a = 0;

并不等于:

extern int;

是否与本地变量相同,写下这样的东西:

int local;

等于:

auto int local;

在这两种情况下,编译器是否默认设置了externauto

文件范围中的extern int a 声明了一个变量,但没有定义它。 这样的声明基本上表示该变量可以在另一个编译单元中找到,并且链接器的工作是在合并各个目标文件时解析其地址。 在这种情况下省略extern将在当前单元中定义变量并将其初始值设置为0 (暂定定义)。 除非使用static ,否则这样定义的变量将具有外部链接(无论extern被省略)。

extern int a = 0是一个定义extern是没有意义的,因为你告诉编译器在这里初始化变量。 在那种情况下,可以安全地省略extern

它和auto吗? 在某种程度上, externauto都是存储类说明符,是的。 但是,自动变量(无论是否使用该关键字定义)不会隐式初始化。 使用未初始化的auto变量是未定义的行为。 此外,无法在函数中声明变量,因此这里的混淆要少得多。

对于联动和外部定义的规则是有点古怪,部分是出于历史原因(参见例如 C89原理)。 对象的规则(它们对于函数声明是不同的)是:

在文件范围:

  • 不允许autoregister ,需要诊断1)
  • static表示内部链接2) ,声明是(暂定)定义3)
  • extern表示已声明的链接,如果没有声明,则表示外部链接4)
  • 没有存储类说明符表示外部链接5) ,声明是(暂定)定义6)
  • 如果多个声明在链接上不一致,则行为未定义7) (Gcc中止编译,我想大多数编译器也是如此)。

暂定定义意味着,对象将在相同的转换单元中定义,如果没有明确的定义,则假设为0 8)多个显式定义是对具有内部链接的标识符的约束违反; 对于具有外部链接的标识符,行为未定义(Gcc中止编译)。 9)

前两个例子大部分都是,但并不完全相同。

int a;

a有外部联系。 宣言是一个暂定的定义; 如果没有显式初始化,则将其初始化为0.如果有另一个声明static int a; ,行为将是未定义的。

extern int a = 0;

另一方面,只有当外部声明已经可见或者没有可见时,才声明a具有外部链接。 如果随后的静态声明a ,行为是不确定的; 如果这之前是一个,则链接将是内部的。 该声明还将a初始化为0,不允许在翻译单元中出现其他明确定义。

extern int a;

(我假设extern int a;而不是extern int;如果你真的是指后者:那是违反约束的。)

这是一个(外部的,如果没有其他声明是可见的)声明没有定义。 通常,定义出现在另一个翻译单元中。 如果在评估它的表达式中使用标识符,它必须出现在某处。

在块范围内:

  • extern意味着与文件范围相同,除了没有暂定定义。 不允许初始化。 10)
  • static表示没有链接(但静态存储持续时间)。 11)如果没有初始化,则将其初始化为0(一次,在程序启动时)。 12)
  • auto或none表示没有链接。 如果没有初始化13) ,变量的值是不确定的,读取这样的值是不确定的(不完全,但实际上)。
  • registerauto类似,但是取其地址是违反约束的。
  • 对于没有链接的标识符(表示对象),不允许重新声明。 14)

因此,最后两个例子是等价的。

这里没有提到的两个存储类说明符是typedef和(因为C11) _Thread_local 15)

参考C11(n1570):

1) 6.9 p2。 2) 6.2.2 p3。 3) 6.9.2 p2。 4) 6.2.2 p4。 5) 6.2.2 p5。 6) 6.9.2 p2。 7) 6.2.2 p7 8) 6.9.2 p2。 9) 6.9 p3和p5。 10) 6.2.2 p4和6.7.9 p5。 11) 6.2.2 p6。 12)13) 6.7.9 p10。 14)6.7 p3。 15)参见 6.7.1。

在此文件中实例化全局变量:

int a;     // instantiation
int a = 0; // instantiation and initialization

编译期间将解析全局变量的地址。


告诉编译器全局变量在另一个文件中实例化:

extern int a;

全局变量的地址将在链接期间解析。


使用extern int a = 0 ,您正在强制实例化a ,从而使得extern无用。

int a; 和extern int a = 0; 是平等的。 当我们初始化一个extern变量时,也会为该变量分配内存,即也会出现与int a;类似的定义。 有关extern的更多信息,请参阅http://www.geeksforgeeks.org/understanding-extern-keyword-in-c

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM