2012-07-31 46 views
2

例如,後我們定義一個變量:當按名稱引用時,名稱的存儲位置在哪裏?

int a=2; 

我們可以用 「a」 作爲2之後。
當我第一次學習c/C++的時候,我認爲這是理所當然的。
但是,當我瞭解到「指針」的概念和變量的地址後,我很困惑。

如果int* p=&i;,其中「i」是一個int。我知道p有我的地址,所以我們可以用* p來得到i的值。但是如果我們走得更遠,如何訪問「p」?似乎p必須按名稱引用,對吧?

現在,通過它的地址訪問一個變量對我來說更加自然,也更容易理解。
但現在,我對使用最簡單的方法訪問變量時的機制感到困惑。
int a=2;的情況一樣,名稱「a」的存儲位置在哪裏?

爲什麼如果我們使用「a」,它相當於訪問存儲「a」或「2」的內存的行爲?

+4

全部編譯完成後,這些符號名稱就沒有任何內容了。它們都被縮減爲內存地址和/或寄存器。變量名稱僅供讀者使用。 – Mysticial 2012-07-31 07:54:35

回答

9

這裏a只是一個象徵性的名字。如果它是一個局部變量,它不會存儲在任何地方。編譯器在編譯階段簡單地使用它,參考實際值(可以在堆棧中或在寄存器中),然後丟棄。

如果您查看編譯器生成的程序集,您會注意到a沒有出現在那裏(或者在註釋中)。編譯器會適合你的變量,然後就使用這個位置(比如x86上的eax寄存器)。

如果你看着一個LLVM組件(這是很有趣的),你會發現,編譯器只是把你的變量@1@2@3 ...

在另一方面,如果a會是一個全局變量(並且不是一個),該名稱實際上將用於符號表中以引用該變量。但反過來說 - 變量會放在沒有名字的地方,符號表會將該名稱映射到該位置,以便其他程序可以找到它。


補充說明:如果程序與調試數據編制,名稱a存儲在那裏,以便調試器可以顯示它可以幫助您瞭解發生了什麼。

3

這被稱爲抽象。故意未指定如何以及在何處存儲a。編譯器會爲你處理它。

實際上,如果a是一個函數內部的局部變量,它將在調用時存儲在該函數的棧幀中。堆棧幀的佈局在編譯時確定,並且在此之後不會改變。實際上,編譯器將生成一個相對地址爲a(相對於堆棧幀的開始),在該函數實際執行時將轉換爲絕對地址,並且堆棧的起始地址 - 幀是已知的。

2

在編譯和鏈接過程之後,「a」和「p」等所有符號都將被轉換爲地址。這些符號僅用於按名稱使用它們的功能。這就像內存地址的標籤。即使「p」保存了「a」的地址,指針「p」也被編譯器改變爲地址。