2014-01-26 74 views
2

我們研究過堆棧的擴展和縮小。但在實踐中它不會發生 乘坐棧擴展的一個例子,從地址100爲0,即第一個變量達到100,然後旁邊99等。現在,當我們編寫以下代碼現在爲什麼堆棧不能回滾

int main() 
{ 
    { 
     int i; 
     cout<<&i;//100 is displayed on screen 
    } 
    { 
     int j; 
     cout<<&j;//99 is displayed on screen 
    } 
} 

當我們宣佈我的時候,它的地址是100,然後它的範圍完成。然後,j被聲明在一個新的作用域中,現在它應該再次擁有地址100,因爲我已經完成了,堆棧應該回退,但是它沒有,j的地址爲99.爲什麼?你可以解釋嗎??

+0

順便說一下,您標記了問題C,但您明確使用C++編譯器。所以我用正確的語言重新標記。 –

+0

獲得更好的編譯器,可以更高效地重用堆棧。 –

+0

@KerrekSB:這可能是完全相同的編譯器,但爲發佈而不是調試構建。在調試模式下,即使在需要變量後,仍然可以看到變量的值。 – MSalters

回答

5

分配棧上的空間需要一些時間,儘管非常小。編譯器進行的一種非常常見的優化是分析函數中聲明的變量,並在函數啓動時同時爲所有變量保留堆棧空間。

一個更聰明的編譯器會意識到兩個變量的生存期不重疊,讓他們共享相同的位置。

6

標準,使局部變量的存儲沒有這樣的承諾。沒有理由相信宣言的順序與他們的記憶順序有任何關係。

這完全是在編譯器它是如何做的遺志。的確,對於你的程序,編譯器可以爲這兩個變量使用相同的地址。我希望任何像樣的優化編譯器都這樣做。

現在,在實踐中,編譯器可能使用各種你談論的優化的。但是,如何實現這些優化會因編譯器而異。而且,你沒有理由描述將普遍適用於所有功能的簡單規則。編譯器可以爲一個功能選擇一種策略,爲不同的功能選擇不同的策略。根據其選項,編譯器的行爲可能會有所不同。

當然,如果你是在談論與函數調用相關的堆棧幀,那麼它是不同的。顯然,當你進行一個新的函數調用時,會分配一個新的堆棧幀。然後當函數返回時,該堆棧框架被銷燬,並且調用函數的堆棧框架被重新輸入。但這是一個完全不同的問題,而不是你在問題中討論的問題。

+0

假設沒有其他進程正在運行,內存是從100分配到0 – Ahmed

+0

爲什麼我們應該假設?爲什麼其他流程是否正在運行非常重要? –

+0

堆棧必須回滾..不是嗎? – Ahmed

0

堆棧將隨時擴展和回滾函數調用的情況下,因爲執行路徑是不是真的可以預測,我們需要存儲局部變量的信息,並調用樹返回每個運行函數地址。

這裏的情況不同,堆棧指針甚至沒有移動,編譯器可以自由優化代碼,併爲兩個小變量使用兩個不同的地址,即使這會導致內存浪費最小。

相關問題