为什么extern int n
在声明n(在不同的文件中)static int n
时无法编译,但在声明int n
时有效? (这两个声明都在文件范围内。)
基本上,为什么文件范围中的int n
与同一范围内的static int n
不一样?它只与extern有关吗?如果是这样,我错过了extern呢?
答案 0 :(得分:112)
static
的全部和全部目的是声明变量对于在中声明的源文件是私有的。因此,它正在完成其防止外部连接的工作。
请记住,文件范围变量定义有四种:
int blah = 0;
- blah在此文件中定义,可从其他文件访问。其他文件中的定义是重复的,会导致错误。extern int blah;
- blah必须在别处定义,并从此文件中引用。int blah;
- 这是FORTRAN COMMON
的道德等同物。您可以在文件中包含任意数量的这些文件,链接器将它们全部解析为一个共享int
。 (*)static int blah;
(可选择使用初始化程序) - 这是静态的。这个文件完全是私有的。其他文件中的externs不可见,并且您可以拥有许多不同的文件,这些文件都声明为static TYPE blah;
,并且它们都不同。对于观众中的纯粹主义者:'file'= 编译单元。
请注意,静态内部函数(不在文件范围内)的范围更加严格:如果两个函数即使在同一个文件中也声明static int bleh = 0;
,它们也是无关的。
(*):对于那些不熟悉的人:在通常的模式中,一个编译单元必须定义一个全局变量,其他人可以引用它。它“存在”在该编译单元中。在上面的情况(3)中,没有文件(或所有文件)定义它。如果两个文件说int blah = 0;
,链接器会抱怨多个定义。如果两个文件说int blah;
,则链接器会愉快地创建一个全局int
并导致所有代码引用它。
答案 1 :(得分:6)
在标准C中,在函数外部声明的变量有两个范围。 static
变量仅在声明它的编译单元(即文件)内可见,并且整个程序中可见非静态变量。 extern
声明表示变量的位置尚未知晓,但将由链接器进行排序;它与非静态变量兼容,但extern static
只是疯狂的谈话!
当然,在实践中,如今还有其他可见性。特别是,现在在单个源文件和整个程序之间存在范围界定;单个共享库的级别是有用的(可通过GCC函数属性等机制设置)。但这只是非静态变量主题的变化; static
保持与以前相同的解释。
答案 2 :(得分:1)
根据MSDN文档:
当修改变量时,static关键字指定变量具有静态持续时间(在程序开始时分配,在程序结束时释放)并将其初始化为0,除非指定了另一个值。 在文件范围内修改变量或函数时,static关键字指定变量或函数具有内部链接(其名称在声明它的文件外部不可见)。
http://msdn.microsoft.com/en-us/library/s1sb61xd(v=vs.80).aspx:2013年6月
答案 3 :(得分:1)
iv.c:2:1:错误:声明说明符中的多个存储类 extern static int i; ^
这就是我们尝试extern一个静态变量。声明extern static int i; - 类似于声明float int i; 你不能让float和int出现在同一个声明中吗?同样,您不能在同一声明中使用extern和static。