考虑由两个文件组成的 C 程序,
f1.c:
int x;
f2.c:
int x=2;
我对the C99 standard第6.9.2段的阅读是这个程序应该被拒绝。在我对6.9.2的解释中,f1.c
中暂定定义了变量x
,但这个暂定定义在翻译单元的末尾变成了实际定义,并且(在我看来),因此应该表现得好像 f1.c
包含定义 int x=0;
。
对于所有编译器(重要的是,链接器),我都能够尝试,但事实并非如此。我试过的所有编译平台都链接了上面两个文件,两个文件中x
的值都是2。
我怀疑这是偶然发生的,或者只是作为标准要求之外提供的“简单”功能。如果您考虑一下,这意味着链接器对那些没有初始值设定项的全局变量有特殊支持,而不是那些显式初始化为零的全局变量。有人告诉我,链接器功能可能是编译 Fortran 所必需的。这将是一个合理的解释。
对此有什么想法吗?标准的其他解释?文件f1.c
和f2.c
拒绝链接在一起的平台名称?
注意:这很重要,因为问题出现在静态分析的上下文中。如果这两个文件在某些平台上可能拒绝链接,分析器应该提示,但如果每个编译平台都接受它,那么就没有理由警告它。
最佳答案
另见 What are extern variables in C .这在信息性附录 J 的 C 标准中作为通用扩展提到:
J.5.11 Multiple external definitions
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).
警告
正如@litb 在这里指出的,以及我在对交叉引用问题的回答中所述,对一个全局变量使用多个定义会导致未定义的行为,这是标准表达“任何事情都可能发生”的方式。可能发生的事情之一是程序的行为符合您的预期; J.5.11 大致说,“你可能比你应得的更幸运”。但是依赖于外部变量的多个定义的程序——有或没有显式的“extern”关键字——不是一个严格符合标准的程序,不能保证在任何地方都能工作。等价地:它包含一个错误,它可能会或可能不会显示出来。
关于c - C 中的暂定定义和链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1490693/