【问题标题】:Point of completion of declaration of a variable变量声明的完成点
【发布时间】:2015-11-26 16:23:32
【问题描述】:

以下代码有用于初始化自身的变量,我很难理解变量声明何时完成,其中一些是非法的,即使它们在 gcc 中编译也是如此。

int main(void)
{
    int a = a;
    int b = (int) &b;
    int c = c ? 1 : 0;
    int d = sizeof(d);
}

【问题讨论】:

    标签: c initialization declaration definition


    【解决方案1】:

    在您的代码中

    int a = a;
    

    是 UB,因为您正在读取一个不确定的值。

    int b = (int) &b;
    

    可以正常编译,因为变量已经分配了内存,但标准不能保证int 能够保存指针的值。所以,从技术上讲,这也将交给 UB。

    int c = c ? 1 : 0;
    

    是 UB,原因与第一个相同。

    int d = sizeof(d);
    

    没问题,在这种情况下,sizeof 在编译时被评估并且值是编译时常量。

    【讨论】:

    • 你能引用相关的 C 标准部分吗?
    • 如果第二个作品依赖于实现。一般来说,使用除(u)intptr_t 以外的任何东西来存储整数中的指针是一个非常糟糕的主意。
    • @bare_metal 我相信 C11 的第 6.7 章应该回答您的问题。 :)
    • @bare_metal 第 J.2 节未定义行为 - 使用一个左值来指定一个可以使用 register 存储类声明的自动存储持续时间的对象在需要指定对象的值的上下文中,但该对象未初始化。 (6.3.2.1)。
    • @bare_metal 同样在 Section J.2 - 与整数类型的转换会产生一个超出可表示范围的值 (6.3.1.4)。
    【解决方案2】:

    这个概念在 C++ 标准(3.3.2 声明点)中有更好的描述,在 C 标准中具有相同的含义

    1 名称的声明点紧随其后 完整的声明符(第 8 条)和 在其初始化程序之前(如果有), 除非下面注明。

    [ Example:
    int x = 12;
    { int x = x; }
    

    这里第二个 x 用它自己的(不确定的)值初始化。 —结束示例]

    在您在此声明中显示的代码示例中

    int a = a;
    

    变量 a 自己初始化。所以它的价值是不确定的。

    此声明

    int b = (int) &b;
    

    有效且变量b具有实现定义的值。

    此声明

    int c = c ? 1 : 0;
    

    其实等价于第一个声明。变量c 具有不确定的值。

    此声明

    int d = sizeof(d);
    

    有效,因为运算符sizeof 中使用的表达式未计算。

    【讨论】:

      【解决方案3】:

      请参阅 C11 规范中的第 6.2.1 节标识符范围。变量的范围在其声明符完成后开始。 declarator 的含义参见Section 6.7.6 Declarators。请注意,initializer(如果存在)位于 declarator 之后,因此被声明的变量在 initializer 的范围内。参见Section 6.7 Declarations了解声明的语法,initializerinit-declarator的一部分,它被定义为

      init-declarator:
           declarator
           declarator = initializer
      

      【讨论】:

        【解决方案4】:

        int a = a;  
        

        a 的定义发生在a 的评估和初始化之前。第二个和第四个声明也是如此,除了第一个和第三个将调用未定义的行为..

        万一

        int c = c ? 1 : 0;  
        

        问题是变量c在初始化之前使用,可能会导致未定义的行为。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-01-11
          • 1970-01-01
          • 1970-01-01
          • 2020-09-25
          • 2011-04-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多