2011-02-27 129 views
12

爲什麼下面的代碼每次都輸出相同的內存位置?C中的For循環局部變量

int x; 
for (x = 0; x < 10; x++) { 
    int y = 10; 
    printf("%p\n", &y); 
} 

我認爲存儲位置應爲每一個for循環運行時間而改變,變量是新的。

回答

18

是的,你是絕對正確的內存位置可能變化。但它不必:)。在每次迭代中,舊變量被「銷燬」,並且在同一個地方「創建」一個新變量。儘管任何體面的編譯器都會優化不必要的「動作」

+0

呵呵,沒關係,謝謝你。我簡化了這個問題,因爲我實際上正在創建一個鏈表,並且我在for循環中創建了一個新節點,並且我不希望下一個節點覆蓋上一次迭代中的節點,但那就是它在做。我會發佈一個新問題,一旦我可以生成一個可以輕鬆分析的代碼片段。 –

+4

如果你想持久化數據結構,他們必須在'堆'而不是'堆棧'上創建。使用'malloc'等。 – Alnitak

+1

@adedeepGrewal:你應該在堆上創建變量(使用malloc)來實現所需的行爲 –

5

是的,變量每次都是新的,但是在塊的結尾再次釋放堆棧中的任何新變量。

因此,下一次堆棧指針回到原來的位置。 NB:這種行爲很普遍,但不保證的標準。

0

變量的作用域規則只描述了你有權訪問局部變量的範圍:從定義到塊的結尾。

這條規則沒有提到空間爲它保留的時刻。一個常見的策略是在函數的開頭爲所有變量保留空間,這些變量是一次調用函數所需要的。

所以,當執行跨越變量的定義時,通常沒有特別的必須完成,而不是單個指令。另一方面,這會將該變量的值留在之前發現的任何值上。所以初始化到一個已知狀態的重要性,就像你在= 10的例子中所做的那樣。

2

這是一個編譯器優化。由於局部變量超出了範圍,並且即將創建完全相同類型的變量,因此它正在重用內存地址。請注意,就程序而言,這仍然是一個「新鮮」或「新」變量。

比較下面的代碼片段輸出:

for (i = 0; i < 3; i++) { 
    int n = 0; 
    printf("%p %d\n", (void *)&n, n++); 
} 
 
0x7fff56108568 0 
0x7fff56108568 0 
0x7fff56108568 0 
for (i = 0; i < 3; i++) { 
    static int n = 0; 
    printf("%p %d\n", (void *)&n, n++); 
} 
 
0x6008f8 0 
0x6008f8 1 
0x6008f8 2