在C和链接暂定定义在C和链接暂定定义(Tentative definitions in C and

2019-05-05 23:15发布

考虑的两个文件组成的C程序,

在f1.c:

int x;

f2.c:

int x=2;

我的第6.9.2读C99的标准是,这个程序应该被拒绝。 在我的6.9.2解释变量x的初步定义f1.c ,但这种试探性的概念却在翻译单元结束的实际定义,以及(在我看来),因此应该表现为,如果f1.c载定义int x=0;

与所有的编译器(并且,重要的是,接头)我能试试,这是不会发生什么变化。 所有编译平台我试着做了以上两个文件链接,和值x是在这两个文件2。

我怀疑这会发生意外,或只是作为一个“易”功能,除了什么标准要求提供。 如果你仔细想想,这意味着在链接器为不具有初始化,而不是那些明确初始化为零的全局变量的特殊支持。 有人告诉我,连接功能可能需要编译的Fortran反正。 这将是一个合理的解释。

这个有什么想法? 该标准的其他解释? 对哪些文件名称平台f1.cf2.c拒绝被联系在一起的?

注:因为在静态分析的环境中出现的问题,这是非常重要的。 如果这两个文件可以拒绝一些平台链接,分析应该抱怨,但如果每个编译平台,接受它,那么就没有任何理由来警告它。

Answer 1:

又见什么是用C的extern变量 。 这在信息附件J作为共同延伸C标准中提到:

J.5.11多重外部定义

可能有一个对象的标识符,具有或不具有明确使用关键字的extern的多于一个的外部定义; 如果定义不同意,或一个以上的初始化,行为是不确定的(6.9.2)。

警告

作为@litb这里所指出的,并在我的答案交叉引用的问题明确规定,通过多个定义为一个全局变量会导致不确定的行为,这是说:“任何事情都可能发生”的标准的方式。 其中一个可能发生的事情是,当你所期望的程序的行为; 和J.5.11说,大约“你可能会幸运往往比你应得的。” 但是,这依赖于外部变量的多个定义程序 - 有或没有明确“的extern”关键字 - 不是一个严格符合程序,并且不保证工作无处不在。 等价的:它包含可能会或可能不会显示自己的错误



Answer 2:

也有一些是被称为“公共扩展”的标准,其中定义变量多次被允许的,只要变量只初始化一次。 见http://c-faq.com/decl/decldef.html

所链接的页面表示,这是恰当的Unix平台 - 我想这是对C99作为C89相同的 - 虽然也许它已经通过更多的编译器,形成某种事实上的标准。 有趣。



Answer 3:

这是我的回答澄清由olovb评论:

纳米用于从编译的目标文件的输出为“int X;”。 在这个平台上,符号都加上了“_”,也就是变量x出现_x。

00000000 T _main
         U _unknown
00000004 C _x
         U dyld_stub_binding_helper

纳米的输出用于从编译的目标文件“INT X = 1;”

00000000 T _main
         U _unknown
000000a0 D _x
         U dyld_stub_binding_helper

纳米的输出用于从编译的目标文件“INT X = 0;”

00000000 T _main
         U _unknown
000000a0 D _x
         U dyld_stub_binding_helper

纳米用于从编译的目标文件的输出“外部INT X;”

00000000 T _main
         U _unknown
         U dyld_stub_binding_helper

编辑:纳米从编译的目标文件的输出“外部INT X;” 其中,x是在的功能的一个实际使用

00000000 T _main
         U _unknown
         U _x
         U dyld_stub_binding_helper


文章来源: Tentative definitions in C and linking