簡體   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