简体   繁体   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");
    }
}

The above code generates the following output: 上面的代码生成以下输出:

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

I'm not able to understand why the second printf value in iterations 2,3,4,5 is 5. 我无法理解为什么迭代2,3,4,5中的第二个printf值是5。

My understanding of why the first value is 0 in each iteration is that the scope of i in the for loop is local and it is destroyed as soon as we go into a new iteration as i was declared in the for loop. 我对每次迭代中第一个值为0的原因的理解是for循环中i的范围是局部的,并且当我们进入新的迭代时它会被销毁,因为ifor循环中声明了它。

But I'm not able to figure out why this value becomes 5 at the second printf . 但我无法弄清楚为什么这个值在第二个printf变为5。

The behaviour of your program is undefined . 程序的行为未定义

The inner scope i is not initialised at the point it's read. 内部范围i在读取时未初始化

(What might be happening is that the reintroduced i on subsequent iterations occupies the same memory as the previous incarnation of the inner i , and the uninitialised memory on the first iteration corresponds to 0. But don't rely on that. On other occasions, the compiler might eat your cat.) 可能发生的是,在后续迭代中重新引入的i占用与内部i的先前化身相同的内存,并且第一次迭代中的未初始化内存对应于0.但是不要依赖于此。在其他情况下,编译器可能会吃你的猫。)

The second printf in your program is printing garbage value from uninitialized local variable i . 程序中的第二个printf是从未初始化的局部变量i打印垃圾值。 In general case the behavior is undefined. 通常情况下,行为未定义。

By accident, storage location that represents your i (memory cell or CPU register) is the same on each iteration of the cycle. 偶然地,代表您的i (存储器单元或CPU寄存器)的存储位置在周期的每次迭代中是相同的。 By another accident, the body of your cycle is executed as a single compound statement for each iteration (as opposed to unrolling the cycle and executing all iterations at the same time in interleaved fashion). 另一个意外,循环的主体作为每次迭代的单个复合语句执行(而不是展开循环并以交错方式同时执行所有迭代)。 By yet another accident, the storage location of i keeps its old value from the previous iteration. 在另一次事故中, i的存储位置保留了之前迭代的旧值。 So, the garbage that you are printing matches the last stored value from that location on the previous iteration of the cycle. 因此,您正在打印的垃圾与循环的上一次迭代中该位置的最后存储值匹配。

That's why you see 5 in local i on each iteration besides the first. 这就是为什么除了第一次迭代之外你在每次迭代中看到本地i 5 On the first iteration that garbage value happened to be 0 . 在第一次迭代中,垃圾值恰好为0

I think this is what is happening: 我想这就是发生的事情:

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 compilers have some latitude in how they implement things and it would not be at all unusual for the local "i" to not actually be recreated each pass of the loop. C编译器在如何实现它们方面有一定的自由度,并且本地“i”实际上不会在循环的每次传递中重新创建都不常见。 It is likely actually only being created once, and re-used on each pass. 它实际上可能只创建一次,并在每次传递时重复使用。 In this case, your first print is outside the scope of the local variable so uses the i from outside the loop. 在这种情况下,您的第一个打印超出了局部变量的范围,因此使用循环外部的i。 The second print uses the local i as it is in scope, and after the first iteration has been set to 5. On the first iteration, the correct value is undefined, not 0, but the behavior of undefined is implementation specific, in your implementation it appears to automatically be initialized to 0. 第二个打印使用本地i,因为它在范围内,并且在第一次迭代设置为5.在第一次迭代时,正确的值是未定义的,而不是0,但undefined的行为是特定于实现的,在您的实现中它似乎自动初始化为0。

If you declare a local variable and don't give it a value before using it, if you get is undefined behavior. 如果声明一个局部变量并且在使用它之前没有给它一个值,那么如果你得到的是未定义的行为。

C standard say, C标准说,

Variables with automatic storage duration are initialized each time their declaration-statement is executed. 每次执行声明语句时,都会初始化具有自动存储持续时间的变量。 Variables with automatic storage duration declared in the block are destroyed on exit from the block. 块中声明的具有自动存储持续时间的变量在从块退出时被销毁。

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

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