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

Mil*_*lan 20 c scope loops shadowing

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Iteration 1 :  0 0
Iteration 2 :  0 5
Iteration 3 :  0 5
Iteration 4 :  0 5
Iteration 5 :  0 5
Run Code Online (Sandbox Code Playgroud)

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

我为什么第一个值在每个迭代是0的理解是,范围i在for环是局部的,但只要我们进入一个新的迭代的破坏i在被宣布for循环.

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

Bat*_*eba 53

程序的行为未定义.

内部范围在读取时i不会初始化.

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

  • "在其他情况下,编译器可能会吃你的猫." 哦加油!不是那个狗屎,编译器!你刚刚在最后一小时吃了50只猫.难怪你多年来已经获得了如此多的安装尺寸与你正在吃的所有猫. (8认同)
  • 击败死马,我已经联系了一个答案,说明为什么它总是UB.陷阱表示或没有陷阱表示无关紧要.正如Antti所说,这是因为它是一个自动变量,没有采用其地址.C11 6.3.2.1. (5认同)
  • 不,`int`可以包含陷阱表示.如果它是`unsigned char`那么你就是对的. (4认同)
  • @Bathsheba甚至不会是正确的.它没有采用其地址,因此它具有未定义的行为.如果它确实有它的地址,它将具有不确定的值(即使unsigned char)并且在库函数中使用它将具有未定义的行为. (3认同)
  • 根据[this](http://stackoverflow.com/a/40674888/584518),它总是UB. (3认同)

AnT*_*AnT 9

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

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

这就是为什么你看到5在本地i上除了第一每次迭代.在垃圾值碰巧的第一次迭代0.


Mil*_*ore 6

我想这就是发生的事情:

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) 
Run Code Online (Sandbox Code Playgroud)