其中用C原因存储对象声明要预约(即是定义)?

问题描述:

C11指定6.7节,其声明也定义:其中用C原因存储对象声明要预约(即是定义)?

的标识符的定义是该标识符的声明:
- 为一个对象,使存储到该对象保留;
[...]

我没有找到一个全面的列表,它的对象声明导致存储被保留。直觉上我很清楚,但我无法从C11标准中获取这些信息。

+0

咦?当我阅读它时,*声明*不会导致任何内容被保留。 –

+1

任何不使用'extern'存储类的。 –

+0

@EugeneSh。每个定义同时是一个声明,反之亦然。 –

没有确定的列表,因为标准只是描述了什么是定义并且它不在一个地方。我会尽量在这里总结一下。我只用型int这里没有一致性任何限定词(如const)。

  • 如果添加初始化器的声明,它总是一个定义

    int x = 1; 
    
  • 如果没有初始化,以下是定义当他们在功能范围

    int x; 
    auto int x;  // auto is the default anyways 
    register int x; // register is just a hint, but would be "storage" as well 
    static int x;  // also reserves storage, but with static duration 
    
  • 文件范围,规则是一个比较复杂;以下是暂定定义

    int x; 
    static int x; 
    

    标准(§6.9.2p2)的措辞:

    的标识符的对象具有文件作用域没有初始化的声明,和 没有存储类说明或与存储类说明static,构成了 暂定定义。如果翻译单元包含一个 标识符的一个或多个试探性的定义,和翻译单元包含该标识符的外部定义,然后 行为是完全一样,如果翻译单元包含 标识符的文件范围内声明,与至0

    复合类型作为翻译单元的端部,具有一个初始化 等于所以这意味着他们最终“成为定义”,如果他们没有找到参考另一个定义。

  • 随着存储类extern并没有初始化,你没有一个定义

    extern int x;  // <- not a definition 
    

AFAIK,这应该是完整的一套规则。如果我忘记了某些东西,请随时编辑/评论。

+0

还有'_Thread_local'声明的情况,它似乎遵循与试探性定义类似的规则,只是标准只在6.7.9中这么说。可能他们不想将它列为临时定义,因为这样的'_Thread_local'声明有效地为每个线程声明了一个对象。 –

+0

很明显,它们不是对象,但也许值得注意的是,在内联函数实例的上下文中,有些令人困惑的重载使用“extern”。坦率地说,我不太明白为什么简单的'inline'和'extern inline'的语义没有颠倒过来。 – doynax