【发布时间】:2011-02-19 23:16:34
【问题描述】:
为什么extern int n 在声明 n 时(在不同的文件中)static int n 不编译,但在声明 int n 时工作? (这两个声明都在文件范围内。)
基本上,为什么文件范围内的int n 与同一范围内的static int n 不一样?它仅与外部有关吗?如果是这样,我错过了 extern 呢?
【问题讨论】:
为什么extern int n 在声明 n 时(在不同的文件中)static int n 不编译,但在声明 int n 时工作? (这两个声明都在文件范围内。)
基本上,为什么文件范围内的int n 与同一范围内的static int n 不一样?它仅与外部有关吗?如果是这样,我错过了 extern 呢?
【问题讨论】:
static 的全部目的是声明一个变量对声明它的源文件是私有的。因此,它在防止来自外部的连接方面恰恰是在做它的工作。
请记住,文件范围变量定义有四种风格:
int blah = 0; — blah 在此文件中定义并可从其他文件访问。其他文件中的定义重复,会导致错误。extern int blah; — blah 必须在别处定义并从此文件中引用。int blah; — 这是 FORTRAN COMMON 的道德等价物。您可以在文件中包含任意数量的这些,并且它们都由链接器解析为一个共享的int。 (*)static int blah;(可选带有初始化程序)——这是静态的。它对该文件是完全私有的。它对其他文件中的外部人员不可见,并且您可以有许多不同的文件都声明static TYPE blah;,并且它们都是不同的。对于听众中的纯粹主义者:'file' = 编译单元。
请注意,静态内部函数(不在文件范围内)的范围更加紧密:如果两个函数即使在同一个文件中声明 static int bleh = 0;,它们也是不相关的。
(*):对于那些不熟悉的人:在通常的模式中,一个编译单元必须定义一个全局变量,其他编译单元可以引用它。它“生活”在那个编译单元中。在上述情况 (3) 中,没有文件(或所有文件)定义它。如果两个文件说int blah = 0;,链接器将抱怨多个定义。如果两个文件说int blah;,链接器会愉快地创建一个全局int,并导致所有代码引用它。
【讨论】:
在标准 C 中,在函数外部声明的变量有两个作用域。 static 变量仅在声明它的编译单元(即文件)内可见,非静态变量在整个程序中可见。 extern 声明表示变量的位置尚不清楚,但将由链接器进行排序;它与非静态变量兼容,但 extern static 简直是疯话!
当然,在实践中,这些天还有其他可见性。特别是,现在在单个源文件和整个程序之间存在范围级别;单个共享库的级别是有用的(可通过 GCC 函数属性等机制设置)。但这只是非静态变量主题的一种变体; static 保持与之前相同的解释。
【讨论】:
根据 MSDN 文档:
修改变量时,static关键字指定变量具有静态持续时间(程序开始时分配,程序结束时解除分配)并将其初始化为0,除非指定另一个值。 在文件范围内修改变量或函数时,static 关键字指定变量或函数具有内部链接(其名称在声明它的文件之外不可见)。
Static (C++) on MSDN:2015年1月存档;另请参阅最新文档:static § Storage classes (C++) | Microsoft Docs
【讨论】:
iv.c:2:1: 错误:声明说明符中有多个存储类 外部静态int i; ^
这就是我们尝试外部静态变量的结果。声明 extern static int i; - 类似于声明 float int i; 你不能让 float 和 int 出现在同一个声明中,对吧?同样,您不能在同一个声明中包含 extern 和 static。
【讨论】: