【发布时间】:2020-08-27 12:35:50
【问题描述】:
问题不是“为什么我不能初始化声明为 extern 的变量”,因为文件范围变量完全可以实现(而不是块范围变量)。问题是 GCC 在这种特殊情况下会产生警告(使用-Wall 开关):
extern int n = 10; // file scope declaration
GCC 产量:
test.c:5:12: warning: ‘n’ initialized and declared ‘extern’
不过,代码运行良好。
此外,请注意,以下定义绝对等同于第一个:
int n = 10; // file scope declaration
在这两种情况下,变量具有相同的链接和存储类型。问题是,由于两者绝对等价,第二个版本在 GCC 中不会产生任何警告(使用 -Wall)。
这是为什么呢?
我的猜测是,您通常使用extern 显式设置一个提醒,即这是一个引用在别处定义的外部对象的声明,因此您不应该(尽管可以)初始化变量(请记住,该标准不允许您在同一链接内定义一个变量两次,在本例中为外部)。
那么,这是一个正确的猜测吗,或者可能还有更多,我看不到?
【问题讨论】:
-
这是 GCC 的一个怪癖——它不是 C 的正常编写方式,编译器会生成警告。最简单的方法是在初始化变量时避免使用
extern。对于旧版本的 C 标准,您会从 GCC 收到警告;它与 C18 无关。 -
我认为这可以归结为“为什么?”。在什么情况下这样做很有用?请参阅 GCC Bugzilla 上 2010 年的 this post。上面的first comment 指出这是关于编码风格的,并将这种模式描述为“非常单一”。
-
一些关于
extern的 C 规则是一团糟,因为随着时间的推移,语言随着不同的实践而演变,导致允许某些事情,禁止其他事情,并赋予某些含义。编译器警告是这种混乱历史的结果。在非定义声明中而不是在定义中使用extern是一种常见的做法,因此编译器会警告它在定义中的使用,但 C 标准允许这样做。 -
@th33lf 好吧,这个问题与禁用警告更相关,就像正在讨论的那样,没有特定的开关。