c - C 中的暂定定义和链接

标签 c compilation fortran static-analysis c99

考虑由两个文件组成的 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.cf2.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/

相关文章:

c - 在 C 中仅使用递归函数和递增进行乘法

c - 当 typedef 是全局而非局部时,为什么定义与函数同名的 typedef 会出错?

c - 在C中,如何根据文件内容退出循环

c++ - 使用 CMake 链接 fortran 和 c++ - 跳过不兼容...错误

c++ - 从 Fortran 调用 C 函数,其中 C 函数名称最初是从 C 传入的

c - 按位掩码

java - 将类转换为不相关的接口(interface)

Java编码编译错误

compilation - Fedora 18 上的内核编译错误(在 Macbook 上的 VirtualBox 上)

fortran - 矩阵乘法程序 : Error: Unclassifiable statement at (1)