内部循环中创建的变量在C中的迭代期间改变值

new*_*low 4 c variables stack for-loop automatic-storage

我的产品代码类似于以下内容.据我说,输出是'0 1 2 3'.但类似代码的输出是'1 1 1 1'.

for(i = 0 ;i < 5;i++){
    int j;
    if(i)
        printf("%d ",j);
    j = i;
}
Run Code Online (Sandbox Code Playgroud)

我的理解是,在'for'循环的整个周期期间,j仅在堆栈上分配一次,并且在迭代期间使用相同的值.另外,如果我将j的声明移到for循环中,我会得到预期的结果.我在这里错过了什么?

PS - 当我在我的个人计算机上运行相同的代码时,我得到了预期的输出.但在生产方面却有所不同.

Sou*_*osh 7

首先,为了清楚自动局部变量的存储持续时间,让我引用C11标准,章节§6.2.4,(强调我的)

声明标识符没有链接且没有存储类说明符的对象static具有自动存储持续时间,[...]

和,

对于没有可变长度数组类型的此类对象,其生命周期从entry进入与其关联的块,直到该块的执行以任何方式结束.(输入一个封闭的块或调用一个函数暂停,但不会结束,执行当前块.)如果以递归方式输入块,则每次都会创建一个新的对象实例.对象的初始值是不确定的.

所以,在你的代码中,每次迭代得到一个新的实例j.什么都没有保留.

在你的代码中,

    int j;   //not initialized
    if(i)
        printf("%d ",j);  //this one here
Run Code Online (Sandbox Code Playgroud)

您正在尝试使用j具有不确定值的单元化自动局部变量.它调用未定义的行为.

根据C11章节§6.7.9

如果未显式初始化具有自动存储持续时间的对象,则其值不确定

和相关的,对于UB,附件§J.2

具有自动存储持续时间的对象的值在不确定时使用.

一旦你的代码命中UB,无论如何都无法证明输出是合理的.

OTOH,当你j在循环外声明时,它有函数范围.然后,与上述情况不同,循环的所有迭代将只有一个实例j.

根据执行流程,第一次,i为0,if将评估为false,printf()将被跳过并将j初始化.然后,在下一次迭代中,当你点击时printf(),会j被初始化,之后一切都很顺利.

  • @RobertHarvey不,每个`j`都是独一无二的.请参见§6.2.4/ 6 (4认同)
  • 难道它不是第一次通过循环UB吗?在第一个循环之后,分配了J. (2认同)