代码之家  ›  专栏  ›  技术社区  ›  Pascal Cuoq

C99中的初步定义和链接

  •  31
  • Pascal Cuoq  · 技术社区  · 15 年前

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

    一层C:

    int x;
    

    F2. C:

    int x=2;
    

    我阅读第6.9.2段 the C99 standard 是否应拒绝此程序。在我对6.9.2的解释中,变量 x 在中暂时定义 f1.c 但是这个暂定的定义在翻译单元的末尾变成了一个实际的定义,因此(在我看来)应该表现得好像 F1.C 包含了定义 int x=0; .

    有了所有的编译器(更重要的是,链接器),我都可以尝试,但这并不是发生的事情。我尝试的所有编译平台都链接了上述两个文件,以及 X 两个文件中都是2。

    我怀疑这是偶然发生的,或者只是作为一个“简单”的特性来提供,除了标准要求的以外。如果您考虑一下,这意味着链接器中对那些没有初始值设定项的全局变量有特殊的支持,而不是那些显式初始化为零的全局变量。有人告诉我,无论如何,要编译Fortran,链接器功能可能是必需的。这是一个合理的解释。

    有什么想法吗?标准的其他解释?文件所在平台的名称 F1.C f2.c 拒绝联系在一起?

    注意:这很重要,因为问题发生在静态分析的上下文中。如果这两个文件可能拒绝在某个平台上链接,那么分析器应该抱怨,但是如果每个编译平台都接受它,那么就没有理由对此发出警告。

    3 回复  |  直到 15 年前
        1
  •  27
  •   Community Egal    7 年前

    也见 What are extern variables in C . 在资料性附录J的C标准中,这是一个常见的扩展:

    J.5.11多重外部定义

    一个对象的标识符可能有多个外部定义,使用或不使用关键字extern;如果定义不一致,或有多个定义被初始化,则行为是未定义的(6.9.2)。

    警告

    正如@litb在这里指出的,正如我对交叉引用问题的回答中所述,对一个全局变量使用多个定义会导致不定义的行为,这是标准的说法“任何事情都可能发生”。可能发生的事情之一是程序的行为如你所期望的那样;J.5.11大致上说,“你可能比你应得的更幸运”。但是一个依赖于一个外部变量的多个定义的程序——有或没有显式的“extern”关键字——并不是一个严格一致的程序,也不能保证在任何地方都能工作。相当于:它包含 缺陷 可能会出现,也可能不会出现。

        2
  •  9
  •   olovb    15 年前

    标准有一个叫做“公共扩展”的东西,只要变量初始化一次,就允许多次定义变量。见 http://c-faq.com/decl/decldef.html

    链接页面说这与Unix平台有关——我猜C99和C89也是一样的——不过也许它已经被更多的编译器采用,形成某种破坏标准。有趣。

        3
  •  7
  •   Pascal Cuoq    15 年前

    这是为了澄清我对OLOVB评论的回答:

    从“int x;”编译的对象文件的NM输出。在这个平台上,符号前面加了一个“u”,也就是说,变量x显示为x。

    00000000 T _main
             U _unknown
    00000004 C _x
             U dyld_stub_binding_helper
    

    从“int x=1”编译的对象文件的NM输出;

    00000000 T _main
             U _unknown
    000000a0 D _x
             U dyld_stub_binding_helper
    

    从“int x=0;”编译的对象文件的NM输出;

    00000000吨干管
    u未知
    000000 A0D×X
    u-dyld_-stub_-binding_助手
    

    从“extern int x;”编译的对象文件的NM输出

    00000000 T _main
             U _unknown
             U dyld_stub_binding_helper
    

    编辑:从“extern int x”编译的对象文件的NM输出;其中x实际用于其中一个函数

    00000000 T _main
             U _unknown
             U _x
             U dyld_stub_binding_helper