如何定义外部变量和声明?

维基说:

extern关键字表示“声明而不定义”。 换句话说,它是一种显式声明变量或强制声明而无需定义的方法。 也可以明确定义变量,即强制定义。 这是通过为变量分配初始化值来完成的

这意味着, 初始化变量的extern声明用作该变量的定义 。 所以,

 /* Just for testing purpose only */ #include  extern int y = 0; int main(){ printf("%d\n", y); return 0; } 

应该是有效的( 在C ++ 11中编译 )。 但是当在GCC 4.7.2中使用选项-Wall -Wextra -pedantic -std=c99进行编译时,会产生一个警告:

 [Warning] 'y' initialized and declared 'extern' [enabled by default] 

哪个不应该。 据我所知,

 extern int y = 0; 

实际上是一样的

 int i = 0; 

这里出了什么问题?

标准的所有三个版本 – ISO / IEC 9899:1990,ISO / IEC 9899:1999和ISO / IEC 9899:2011 – 在标题外部对象定义 (C90的第6.7.2节和§)的部分中包含一个示例。 C99和C11的6.9.2)显示:

例1

 int i1 = 1; // definition, external linkage static int i2 = 2; // definition, internal linkage extern int i3 = 3; // definition, external linkage int i4; // tentative definition, external linkage static int i5; // tentative definition, internal linkage 

示例继续,但extern int i3 = 3; 线条清楚地表明标准表明应该允许。 但请注意,标准中的示例在技术上并非“规范”(参见标准中的前言); 它们不是对允许和不允许的最终陈述。

也就是说,大多数人大多数时候不使用extern和初始化器。

此代码完全有效。

但任何编译器都可以自由发布其他(信息性或非信息性)诊断:

(C99,5.1.1.3p1 fn 8)“当然,只要有效的程序仍然正确翻译,实现就可以自由地产生任意数量的诊断。”

当存在约束或语法违规时,编译器不能执行的操作不会发出诊断信息。

编辑:

由于devnull提出了OP问题的评论, gcc团队的Joseph Myers在一个错误报告中解释了质疑这个诊断:

“这是一种编码风格警告 – 代码是有效的,但对于C来说非常单一,因为”extern“通常被认为意味着声明没有提供对象的定义。”