繁体   English   中英

当变量未初始化时,为什么这个程序会产生奇数输出?

[英]Why does this program produce odd output when the variable is uninitialized?

int main() {
    int j = 0;
    int i = 0;
    for (j = 0; j < 5; j++) {
        printf("Iteration %d :  %d ", j + 1, i);
        int i;
        printf("%d", i);
        i = 5;
        printf("\n");
    }
}

上面的代码生成以下输出:

Iteration 1 :  0 0
Iteration 2 :  0 5
Iteration 3 :  0 5
Iteration 4 :  0 5
Iteration 5 :  0 5

我无法理解为什么迭代2,3,4,5中的第二个printf值是5。

我对每次迭代中第一个值为0的原因的理解是for循环中i的范围是局部的,并且当我们进入新的迭代时它会被销毁,因为ifor循环中声明了它。

但我无法弄清楚为什么这个值在第二个printf变为5。

程序的行为未定义

内部范围i在读取时未初始化

可能发生的是,在后续迭代中重新引入的i占用与内部i的先前化身相同的内存,并且第一次迭代中的未初始化内存对应于0.但是不要依赖于此。在其他情况下,编译器可能会吃你的猫。)

程序中的第二个printf是从未初始化的局部变量i打印垃圾值。 通常情况下,行为未定义。

偶然地,代表您的i (存储器单元或CPU寄存器)的存储位置在周期的每次迭代中是相同的。 另一个意外,循环的主体作为每次迭代的单个复合语句执行(而不是展开循环并以交错方式同时执行所有迭代)。 在另一次事故中, i的存储位置保留了之前迭代的旧值。 因此,您正在打印的垃圾与循环的上一次迭代中该位置的最后存储值匹配。

这就是为什么除了第一次迭代之外你在每次迭代中看到本地i 5 在第一次迭代中,垃圾值恰好为0

我想这就是发生的事情:

Breakpoint 1, main () at abc.c:4
4       int j = 0;
(gdb) s
5       int i = 0;
(gdb)
6       for(j=0;j<5;j++){
(gdb) p &i
$23 = (int *) 0x7fff5fbffc04           //(1) (addr = 0x7fff5fbffc04) i = 0
(gdb) p i
$24 = 0                                              // (2) i == 0
(gdb) s
7           printf("Iteration %d :  %d ",j+1,i);
(gdb) p &i
$25 = (int *) 0x7fff5fbffc00            //(3) here compiler finds there is contention in variable 'i' and assigns the inner one which is in present scope. Now, when subroutines are called, the stack frame is populated with (arguments, return address and local variables) and this is when the inner 'i' was also got allocated in this inner loop block but not initialized yet and this is the reason i get garbage value in the first integration output.

(gdb) p i
$26 = 1606417440                          // (4)  Here i == 1606417440 (Garbage)
(gdb) s
9           printf("%d",i);
(gdb) s
10          i = 5;
(gdb) p &i
$27 = (int *) 0x7fff5fbffc00
(gdb) p i
$28 = 1606417440
(gdb) s
11          printf("\n");
(gdb) p &i
$29 = (int *) 0x7fff5fbffc00
(gdb) p i                                                //(5) after executing previous statement, now i == 5
$30 = 5
(gdb) 

C编译器在如何实现它们方面有一定的自由度,并且本地“i”实际上不会在循环的每次传递中重新创建都不常见。 它实际上可能只创建一次,并在每次传递时重复使用。 在这种情况下,您的第一个打印超出了局部变量的范围,因此使用循环外部的i。 第二个打印使用本地i,因为它在范围内,并且在第一次迭代设置为5.在第一次迭代时,正确的值是未定义的,而不是0,但undefined的行为是特定于实现的,在您的实现中它似乎自动初始化为0。

如果声明一个局部变量并且在使用它之前没有给它一个值,那么如果你得到的是未定义的行为。

C标准说,

每次执行声明语句时,都会初始化具有自动存储持续时间的变量。 块中声明的具有自动存储持续时间的变量在从块退出时被销毁。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM