块内变量的声明也是定义吗?

Is a declaration of a variable inside a block also a definition?

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

C11 6.7/5

A definition of an identifier is a declaration for that identifier that:

— for an object, causes storage to be reserved for that object;

(...)

那么块内的变量声明也是定义吗?例如:

void Bla(void) {
    int a; // Is this declaration also a definition?
}

我在Whosebug上找到了以下两个答案,其中声明块内的变量声明也是定义:

但是"Michael Burr"的回答参考了6.2.2/2"Linkages of identifiers",以说明块作用域中的变量声明也是定义。对我来说,他的参考并没有回答我的问题。第二个 link 中的答案没有提供对 C 标准的任何参考。 C标准中是否还有其他段落可以作为参考来确认这些答案?

请提供对 C 标准的引用。

C standard 的第 6.2.2p6 节指出:

In the set of translation units and libraries that constitutes an entire program, each declaration of a particular identifier with external linkage denotes the same object or function. Within one translation unit, each declaration of an identifier with internal linkage denotes the same object or function. Each declaration of an identifier with no linkage denotes a unique entity.

缺少的部分是第 6.2.2p6 节:

The following identifiers have no linkage: an identifier declared to be anything other than an object or a function; an identifier declared to be a function parameter; a block scope identifier for an object declared without the storage-class specifier extern.

在没有存储 class 说明符(即 staticextern)的块内声明的变量 没有链接 ,并且每个没有链接的变量声明都是一个唯一的对象。因为声明是唯一的,所以它也有资格作为定义。

另见第 6.7p7 节:

If an identifier for an object is declared with no linkage, the type for the object shall be complete by the end of its declarator, or by the end of its init-declarator if it has an initializer; in the case of function parameters (including in prototypes), it is the adjusted type (see 6.7.6.3) that is required to be complete.

是的,在块范围内声明 "object"(C 标准避免使用单词 "variable")是一个定义,除非该对象的声明使用存储 -class 说明符 extern,在这种情况下它不是定义。

以下是如何从标准中看出这一点(所有引用均参考 N1570,这是最接近免费公开提供的 C2011 官方文本的近似值):

首先,6.2.2p6

the following identifiers have no linkage: ... a block scope identifier for an object declared without the storage-class specifier extern.

秒,6.7p5

A definition of an identifier is a declaration for that identifier that: * for an object, causes storage to be reserved for that object;

最后是 6.2.4,您需要完整阅读,但最重要的部分在第 5 段和第 6 段中:

An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration ... its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way.

因此,如果您在没有 extern 的情况下在块范围内声明一个对象,它就没有链接。没有链接的对象具有自动存储持续时间,除非它是用 static 声明的,在这种情况下它具有静态存储持续时间,请参阅我没有引用的 6.2.4 部分。具有自动存储持续时间的对象在进入其声明的块时为其保留了存储空间,而具有静态存储持续时间的对象在程序启动时为其保留了存储空间(再次参见 6.2.4 的部分我没有引用)。因此,任何没有链接的对象声明都是定义。

(在块作用域 extern 中声明一个对象为其提供外部链接并且 不是 定义。如果您在阅读了我引用的所有部分以及 6.9 后不明白为什么会这样,请专门提出一个新问题。)