我得到了答案,这可以作为我问题的例子。
代码
#include <stdio.h>
int main(void) {
int i = 0;
back:
printf("i = %d", i);
int j;
if (i < 5) {
if (i == 0)
j = 0;
j += i;
printf(", j = %dn", j);
i++;
goto back;
}
printf("n");
}
输出
i = 0, j = 0
i = 1, j = 1
i = 2, j = 3
i = 3, j = 6
i = 4, j = 10
i = 5
但有人说";j
的值在达到其声明时变得不确定"因为C17 6.2.4p6(用我的粗体(
对于这样一个没有可变长度数组类型的对象,其生存期从条目开始延长直到该块的执行以任何方式结束。(输入封闭的块或调用函数会挂起但不会结束当前块的执行。(如果块是递归输入的,每次都会创建一个新的对象实例对象的初始值是不确定的。如果为对象指定了初始化,则每次在块的执行中达到声明或复合文字时都会执行该初始化;否则,每次到达声明时,该值都会变得不确定。
只转到当前块中的标签与在递归函数或迭代语句中重复整个关联块不同。从这个角度来看,我不认为j
不受规则的影响(但这只是我的想法(
顺便说一句,不管我们怎么想,我都认为存在矛盾
-如果int j;
没有在每个序列中重新创建,则它是一个重新定义
-如果在每个序列中重新创建int j;
,则j
将具有来自第二个序列的垃圾值。但输出显示为保留了"j"的值
我反复阅读引用的部分文档,但无法理解。我缺少什么?
重要的部分在后面:
如果为对象指定了初始化,则[…];否则,每当达到声明时,该值就会变得不确定。
每次达到int j
时,j
的值都变得不确定。保留先前值的j
也是垃圾值的一个示例,因为它可以是任何值。如果您的代码依赖于该值,则意味着您的代码的行为没有定义。
如果块是递归输入的,则每次时都会创建对象的新实例
;块";通常是以CCD_ 9开始并以}
结束的东西。那一段是递归函数。
void func()
{ // block start
int a; // new instance of object created each time, even recursively
func(); // enter the block recursively
} // block end
代码中有一个块是用int main(void) {
创建的,代码中的另一个块就是if (i < 5) {
之后的块if (i < 5) {
块不是递归输入的,它是输入的,然后离开,然后再次输入,然后再次离开。
如果int j;不是在每个序列中都重新创建的,而是一种重新定义。
引用该报价:
对于这样一个没有可变长度数组类型的对象[具有自动存储持续时间的对象,请参阅标准中的前一点],其生存期将从进入与其关联的块开始延长,直到该块的执行以任何方式结束。
j
标识的对象的生存期从进入块开始,所以我认为它不是";重新创造";。
int main(void) { // lifetime of "object j" starts here
// but you can't access it, no identifier is associated with it
back:;
int j; // the identifier `j` is associated with "object j"
// the value of the object associated with `j` is indeterminate
// _each time_ execution flow gets here
goto back;
} // lifetime of "object j" ends here (or at `return`)
// scope of identifier `j` also ends here