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

时间:2018-08-19 18:23:23

标签: c language-lawyer declaration definition c11

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

  

C11 6.7 / 5

     

标识符的定义是该标识符的声明   

     

-对于一个对象,导致为该对象保留存储空间;

     

(...)

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

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

我在stackoverflow上发现了以下两个答案,它们指出块内变量的声明也是定义:

但是,“ Michael Burr”提供的答案是指6.2.2 / 2“标识符的链接”,以便解释块范围内的变量声明也是定义。对我而言,他的参考文献无法回答我的问题。第二个链接中的答案未提供对C标准的任何引用。 C标准中是否还有其他段落可以用作确认这些答案的参考?

请提供对C标准的引用。

2 个答案:

答案 0 :(得分:7)

是的,在块范围内的“对象”声明(C标准避免使用单词“变量”)是一个定义,除非该对象的声明使用存储类说明符extern,在这种情况下,这不是一个定义。

以下是从标准中看到的内容(所有参考文献均为N1570,这是与C2011官方文本最接近的近似文本,可免费获得):

首先,6.2.2p6

  

以下标识符没有链接:...声明的没有存储类说明符extern的对象的块作用域标识符。

{p>秒,6.7p5

  

标识符的定义是对该标识符的声明:   *对于一个对象,导致为该对象保留存储空间;

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

  

一个其标识符声明为无链接且没有存储类说明符为static的对象具有自动存储持续时间...其生存期从进入与之相关联的块开始,直到该块的执行以任何方式结束。

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

(在块范围中带有 extern的对象声明为其提供了外部链接,并且不是 的定义。如果看不到为什么是在阅读完我引用的所有部分以及6.9之后,请专门提出一个新问题。)

答案 1 :(得分:4)

C standard的第6.2.2p6节规定:

  

在一组翻译单元和库中,   构成一个完整的程序,每个特定的声明   具有外部链接的标识符表示同一对象或   功能。在一个翻译单位中,每个   具有内部链接的标识符表示相同的对象或   功能。 每个没有链接的标识符声明   表示唯一实体。

缺少的部分是第6.2.2p6节:

  

以下标识符没有链接:声明为   除对象或功能以外的任何事物;标识符   声明为函数参数; 块范围标识符   声明没有存储类说明符extern的对象。

在没有存储类说明符(即staticextern)的块内声明的变量没有没有链接,并且每个变量的声明都带有没有链接是唯一的对象。由于声明是唯一的,因此它也可以视为定义。

另请参阅第6.7p7节:

  

如果声明的对象标识符没有链接,   对象的类型应在其末尾完成   声明符,如果有,则在其init声明符的末尾   初始化器;如果是功能参数(包括   原型),则需要调整后的类型(请参见6.7.6.3)   完成。