c - 循环体中声明的变量在迭代过程中是否被保留?

标签 c loops scope variable-declaration

考虑 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' |

我认为从语言的角度来看这是逻辑行为:自动变量在 block 终止后消失,因此应该预期上述“随机”行为。

正确的行为应该是什么? 我知道将 x 的声明移到循环之外可以“修复”它,但这并没有说明此代码段的行为。现实世界的问题是bug in Netfilter .

最佳答案

由于数组是在循环体的范围内声明的,因此您可以将其视为在每次循环迭代的自动存储区域中分配一个新数组。该单位初始化数组的内容是未定义的,除了您在当前迭代期间分配给的索引处的字符之外,因此您看到的是不确定的值:

C99 standard, section 6.7.8: If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate

当优化关闭时,数组会落在自动存储中的同一位置,因此您的程序会很幸运;然而,这并不能得到保证。

将数组移动到循环之外,如下所示:

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;
    }
}

关于c - 循环体中声明的变量在迭代过程中是否被保留?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11650905/

相关文章:

c++ - 我有一些范围问题(for 循环后出现身份不明的标识符错误)

c - 尝试二分查找

c++ - 模拟窗口的移动并让它对碰撞使用react

c++ - 通过左移,可以将1设置为零

C 为什么可以声明具有可变大小(但固定列)的二维数组的函数

c++ - 对临时对象的 const 引用在函数作用域(生命周期)后被破坏

python - 我想生成一个循环来查找多列的 groupby 平均值

c - 在 C 中,有哪些方法可以使函数在其调用之间共享数据?

php - 处理 php 中的空循环

Javascript 变量作用域之谜