是一个变量在迭代过程中保留一个循环体中声明?(Is a variable declared in a

2019-09-20 04:02发布

考虑在C环,其声称,在该循环体的字符数组。 在每次迭代中,阵列的一个字符被修改,直到达到终点。 在结束时,该变量被打印。 该说明将扩大到下一个代码:

#include <stdio.h>

int main(void) {
    int i = 0;
    for (;;) {/* same as: while(1) { */
        char x[5];
        x[i] = '0' + i;
        if (++i == 4) {
            x[i] = '\0'; /* terminate string with null byte */
            printf("%s\n", x);
            break;
        }
    }
    return 0;

很多人可能会想到0123作为输出。 但由于某些原因GCC 4.7没有做优化启用(编译时-O1及更高版本)。 它而不是把随机数据在字符数组,成为第一字节:

| 0  |  1  |  2  |  3  |  4   |
|     RANDOM     | '3' | '\0' |

我认为这是从语言角度逻辑的行为:一个块结束后自动变量都消失了,所以上面的“随机”的行为应该可以预期的。

什么应该是正确的行为? 我知道,移动的声明x外循环“修复”,但不说这个片段的行为,任何东西 。 在现实世界中的问题是在Netfilter的错误 。

Answer 1:

由于数组循环体的范围内声明的,你可以把它作为一个新的阵列中的每个循环迭代自动存储区域被分配。 该unititialized阵列的内容是不确定的,除了到您在当前迭代过程中分配的索引中的字符,所以你看到有不确定的值:

C99标准,部分6.7.8:如果具有自动存储持续时间的对象没有被明确初始化,它的值是不确定的

当优化被关闭,在自动存储在同一个斑点阵列的土地,所以你的程序得到的幸运; 然而,这是无法保证的装置。

该阵列移动到环的外侧,这样的:

int i = 0;
char x[5];
for (;;) {
    x[i] = '0' + i;
    if (++i == 4) {
        x[i] = '\0'; /* terminate string with null byte */
        printf("%s\n", x);
        break;
    }
}


Answer 2:

这是块范围的问题。 循环体是嵌段,表示为{}这是进入和离开在每次循环迭代。 每次进入该块的时候,你(概念),新的x与非特定内容。

因为你只设定x[3] = '3'x[4] = '\0'在迭代printf被调用时,只有这两个阵列成员具有良好定义的内容。 其余部分可包含任何东西,包括'\0' ,所以printf至多2可以输出长度的任何串,任选接着进行任何其他字符和3



Answer 3:

这将如预期(随机字符数组)的输出,如一个自动变量声明它终止范围之后被清除。 要修复,移动x的范围之外for循环。



Answer 4:

该阵列将为每个迭代中分配的内存,它会在只有最后一次迭代获得的价值。



文章来源: Is a variable declared in a loop body preserved during iterations?