There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).
多么尴尬的一段话,我们可以理解为gcc 和 vc允许在整个程序编译过程中的“tentative definition”,而非单一个"translation unit"内。
那么我们便可以理解之前两个int a的不会报错的场景了。gcc vc 视这样的没有初始化的变量为extern而非define。
同样可以理解的是,如果我们添加了初始化值:
int a = 0;
int a = 0;
int main(void){
return 0;
}
则会报错了:
➜ t cc t1.cpp
t1.cpp:5:5: error: redefinition of 'a'
int a;
^
./t1.h:4:5: note: previous definition is here
int a ;
^
t1.cpp:6:5: error: redefinition of 'a'
int a;
^
./t1.h:4:5: note: previous definition is here
int a ;
^
2 errors generated.
结合tentative definition的定义,便不难理解了。
到这里,细心的读者可能发现,我们这里的tentative definition只局限于C语言,是的。C++并不认可这一概念,把所有的int a; 视为变量定义。所以,如果使用c++,这些又会全部变成 redefinition 或者 duplicate symbol了。
吐槽:一个看似简单的问题,查阅了一天的资料,引申出这么多概念,才彻底弄明白,我真的学过C嘛( ⊙ o ⊙ )?