首先,为了明确关于自动局部变量的存储持续时间,让我引用C11
标准,第 §6.2.4 章,(强调我的)
其标识符被声明为没有链接且没有存储类说明符的对象static
具有自动存储持续时间,[...]
和,
对于这样一个没有可变长度数组类型的对象,它的生命周期从进入与其关联的块开始,直到该块的执行以任何方式结束。(进入封闭的块或调用函数会暂停,但不会结束当前块的执行。)如果递归地进入块,则每次都会创建一个新的对象实例。对象的初始值是不确定的。
因此,在您的代码中,每次迭代都会获得一个新的j
. 什么都没有保留。
在您的代码中,
int j; //not initialized
if(i)
printf("%d ",j); //this one here
您正在尝试使用j
具有不确定值的未初始化的自动局部变量。它调用未定义的行为。
根据C11
第 §6.7.9 章
如果具有自动存储持续时间的对象未显式初始化,则其值是不确定的
和相关的,对于 UB,附件 §J.2
具有自动存储持续时间的对象的值在不确定时使用。
一旦您的代码到达 UB,无论如何,输出都无法证明是合理的。
OTOH,当您j
在循环外声明时,它具有函数范围。然后,与上述情况不同,循环的所有迭代都只有一个实例。j
根据执行流程,第一次i
为 0,if
将评估为 false,printf()
将被跳过并被j
初始化。然后,在下一次迭代中,当你点击 , 时printf()
,j
它会被初始化,此后一切都很好。