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