c - C 中的哪些对象声明导致存储被保留(即定义)?

标签 c language-lawyer c11

C11 在第 6.7 节中指定哪些声明也是定义:

A definition of an identifier is a declaration for that identifier that:
— for an object, causes storage to be reserved for that object;
[...]

我没有找到关于哪些对象声明导致存储被保留的完整列表。直觉上我很清楚,但我无法从 C11 标准中获取此信息。

最佳答案

没有明确的列表,因为该标准只是描述了什么是定义,而且它不在一个地方。我会在这里总结一下。为了保持一致性,我将在此处仅使用 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) 的措辞是:

    A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier static, constitutes a tentative definition. If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0

    所以这意味着如果没有发现它们引用另一个定义,它们最终将“成为定义”。

  • 使用存储类 extern 并且没有初始化程序,您没有定义:

    extern int x;     // <- not a definition
    

据我所知,这应该是一套完整的规则。如果我忘记了什么,请随时编辑/发表评论。

关于c - C 中的哪些对象声明导致存储被保留(即定义)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45694056/

相关文章:

c++ - 在父类内部定义子类的子结构

c++ - 使用 std::initializer_list 的 constexpr 的奇怪行为

c - 递归调和函数返回 NaN

c - C 语言的消息调度系统不会破坏严格的别名和对齐

c - 使用不兼容类型调用的没有原型(prototype)的函数

c - int main() { }(没有 "void")在 ISO C 中有效且可移植吗?

c - 序列点和副作用 : Quiet change in C11?

c - 为什么 gcc(或 glibc)不实现 _s 函数?

c - 在 if 语句中使用 strcmp

c - 无法比较 C 中的值