简体   繁体   中英

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.

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.

But I'm not able to figure out why this value becomes 5 at the second printf .

The behaviour of your program is undefined .

The inner scope i is not initialised at the point it's read.

(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.)

The second printf in your program is printing garbage value from uninitialized local variable 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. 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. 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. On the first iteration that garbage value happened to be 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. 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. 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.

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,

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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