此代码没有未定义的行为。我们可以在6.2.4 部分的 Rationale for International Standard—Programming Languages—C 中找到一个很好的例子对象的存储持续时间 它说:
[...]有一个简单的经验法则:声明的变量被创建
输入块时具有未指定的值,但
初始化器被评估并且值被放置在变量中时
在正常执行过程中达到声明。这样一跳
向前超过声明使其未初始化,而跳转
向后将导致它被多次初始化。如果
声明不会初始化变量,它会将其设置为
未指定的值,即使这不是第一次声明
已到达。
变量的作用域从它的声明开始。因此,虽然
变量一进入块就存在,不能
在到达声明之前按名称引用。
并提供以下示例:
int j = 42;
{
int i = 0;
loop:
printf("I = %4d, ", i);
printf("J1 = %4d, ", ++j);
int j = i;
printf("J2 = %4d, ", ++j);
int k;
printf("K1 = %4d, ", k);
k = i * 10;
printf("K2 = %4d, ", k);
if (i % 2 == 0) goto skip;
int m = i * 5;
skip:
printf("M = %4d\n", m);
if (++i < 5) goto loop;
}
输出是:
I = 0, J1 = 43, J2 = 1, K1 = ????, K2 = 0, M = ????
I = 1, J1 = 44, J2 = 2, K1 = ????, K2 = 10, M = 5
I = 2, J1 = 45, J2 = 3, K1 = ????, K2 = 20, M = 5
I = 3, J1 = 46, J2 = 4, K1 = ????, K2 = 30, M = 15
I = 4, J1 = 47, J2 = 5, K1 = ????, K2 = 40, M = 15
它说:
在哪里“??????”表示一个不确定的值(以及任何使用
不确定的值是未定义的行为)。
此示例与草案 C99 标准部分 6.2.4 对象的存储持续时间第 5 段一致,其中说:
对于这样一个没有变长数组类型的对象,
它的生命周期从进入它所在的块开始
关联,直到该块的执行以任何方式结束。 (输入一个
封闭的块或调用函数挂起,但没有结束,
执行当前块。)如果块是递归进入的,
每次都会创建一个新的对象实例。初始值
对象的不确定性。如果指定了初始化
对象,每次到达声明时都会执行
块的执行;否则,值变得不确定
每次达到声明。