2016-08-14 159 views
-4

我想知道爲什麼這段代碼沒有按預期工作。堆棧是否連續增長?

typedef char uint8; 

    int main(int argc, const char * argv[]) { 
    // insert code here... 

    uint8 number_1 = 3; 
    uint8 number_2 = 1; 
    uint8 *PointerToNumber = &number_1; 

    printf("%d \n", *PointerToNumber); 
    ++PointerToNumber; 
    printf("%d \n", *PointerToNumber); 

    return 0; 
} 

該程序打印3和-112。但是,如果堆棧不斷增長,它不應該打印3和1嗎?

因此,如果我指向number_1,然後增加類型爲uint8的指針地址不應該指向number_2,因爲它是在number_2之後聲明的?

+7

這不是堆棧增長的問題,而是編譯器如何選擇排列局部變量的問題。 –

+3

兩個變量之間可能有未使用的字節......並且不能保證變量被放置在任何特定的位置或順序中,或者甚至被包括在內(根據它們的使用方式,它們可以被優化)。 – Dmitri

+0

不能依賴於局部變量在內存中的位置,但'number_2'可能位於'number_1'後面的下一個較低地址處。 –

回答

3
++PointerToNumber; 
printf("%d \n", *PointerToNumber); 

導致未定義的行爲。試圖證明任何行爲是毫無意義的。程序的行爲可能隨着優化級別,不同編譯器選項和不同編譯器的更改而改變。

在這種情況下,優化程序可以選擇不爲number_2分配任何空間,因爲它沒有在函數中使用。

0

好像有人評論過,number-2可能在number_1之後的下一個較低的地址。 因此,而不是在執行++ PointerToNumber,--PointerToNumber創建預期結果(打印「1」)。

+0

再次,沒有保證。嘗試編譯優化,看看它是否仍然有效。另外,通過優化,我可以得到您期望的原始代碼的結果,因爲我的編譯器對變量進行了不同的排序,並且優化後的結果都不起作用。 – Dmitri

+0

是的,我知道這一點。我只想驗證堆棧的整體概念作爲LIFO內存。 – user148013

+0

局部變量的放置與作爲LIFO的堆棧無關。當一個函數被調用時,通常發生的事情是調用者將參數和返回地址壓入堆棧並調用該函數。被調用函數然後將幀指針設置爲堆棧指針的值。然後,堆棧指針會減少函數爲本地存儲所需的空間量。局部變量被分配到該空間中的位置(表示爲來自幀指針的負偏移),但它們可以在那裏的任何位置。這完全取決於編譯器。 –