C 裏面 ---變量名-- 和 --地址-- 的關係探討


本文爲轉載,原出處暫不明確,多謝原作者!


變量名不佔空間
變量:用來標識(identify)一塊內存區域,這塊區域的值一般是可以更改的,這就是它“變”的由來,但是我們可以通過使用如const等一些修飾符號來限定這一內存區域的操作特性(characteristic),即變量的操作特性。用const修飾的使變量不能更改的就和常量一樣的變量叫做常變量。
變量名:是一個標識符(identifier),用來指代一塊內存區域,即變量,使用變量使我們操作內存以區域(area),以塊(block)爲單位,提高了方便性。
你的機器代碼中,是不會出現變量名的;變量名是給我們程序員操作內存來使用的。
想想在彙編年代,沒有變量名,我們操作內存,都是用地址來直接操作的,還要控制區域大小;當然彙編語言已經有了簡單的變量。
對於編譯器,它會蒐集我們的變量名,比如我們定義了一個全局的int a;那麼編譯器都爲我們做了什麼呢?
它會爲程序預留4個字節的空間(假設在32位平臺),並把我們的變量名“a”保存進符號表,並用這個符號表的索引對應實際的空間。
如果下面出現b = a;那麼它就會根據符號表找到變量的真正的物理位置,取得它的值,賦給b。
這是寫編譯器需要做的,我們需要建立符號表。
但是實際在彙編層次上,操作的都是地址而已,不存在任何名稱了。

 

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

除了變量名不是內存地址,其他名都是地址。對麼?

 

所謂的其他名無非是函數名、標識符常量名、指針名、數組名、結構名、類名等等。  
   
  樓主的話有部分是對的,  
   
  比如指針名、數組名、函數名就是地址,它們分別表示指針所指向元素的地址、數組的首地址和函數的入口地址。  
   
  變量名雖然不直接表示地址,但可用取地址符號&來獲得它所代表的變量的存放地址。因爲在定義變量的同時會分配給它相應的空間。  
   
  但類和結構只有事例化時才爲它分配空間,從而不能用取地址符號&來獲得類名或結構名的地址。

 

變量名是用來標識某個內存塊的  
  地址就是地址啦,如是變量名的話,用取地址運算符&就可以得到它標識的內存塊的地址,  
  而指針變量呢,它本身也是一個變量名,只不過它標識的那塊內存存放的是一個地址值  

 

變量是地址的別名..就像剛生的小孩,你只知道他在地球上的某個位置,而不能叫出他名字,給你取個名

 

 

~~~~~~~~~~~~~~~~~~~~~~~

 

定義int a;時,編譯器分配4個字節內存,並命名該4個字節的空間名字爲a(即變量名),當用到變量名a時,就是在使用那4個字節的內存空間.
5是一個常數,在程序編譯時存放在代碼的常量區存放着它的值(就是5),當執行a=5時,程序將5這個常量拷貝到a所在的4個字節空間中,就完成了賦值操作.

a是我們對那個整形變量的4個字節取的"名字",
是我們人爲給的,實際上計算機並不存儲a這個名字,只是我們編程時給那4個字節內存取個名字好用.實際上程序在編譯時,所有的a都轉換爲了那個地址空間了.編譯成機器代碼後,沒有a這個說法了.a這個名字只存在於我們編寫的代碼中.
5不是被隨機分配的,而總是位於程序的數據段中,可能在不同的機器上在數據段中的位置可能不一致,它的地址其實不能以我們常用到的內存地址來理解,因爲牽扯到一個叫"計算機尋址方式"的問題,所以寫很多都解釋不清楚,你自己找本彙編語言的書來學一下吧.........

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~

C語言中變量只是標識對應存儲單元內的存儲內容。與地址的對應關係
int a=3;
a---&a

 

一一對應啊,變量名只是一個便於記憶識別的名稱,編譯器會將他編譯成相應的內存地址的.

變量都要佔據一定的內存。
通過定義該變量的指針, [類型]* 指針名=你要指向的變量名
那麼該指針中存儲的就是你的變量的內存地址。
&你的變量名    這樣就可以直接獲取到你的變量地址
或者定義引用 [類型]& 引用名=變量名
該引用可通過變量的地址來對變量進行修改

 ~~~~~~~~~~~~~~~~~~~~~~~~~

變量名是給編譯器看的,編譯器根據變量是局部還是全局分配內存地址或棧空間,所謂的變量名在內存中不存在,操作時轉換成地址數存放在寄存器中了。

編譯器會將合法的變量名放到一個叫“符號表”的一個表中。
每個符號對應一個地址。當你調用此變量時,就會根據此符號表找到對應的地址,然後進行操作。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

還沒有運行怎麼會佔用內存呢?!(這一點還要懷疑嗎!?)

所謂在編譯期間分配空間指的是靜態分配空間(相對於用new動態申請空間),如全局變量或靜態變量(包括一些複雜類型的常量),它們所需要的空間大小可以明確計算出來,並且不會再改變,因此它們可以直接存放在可執行文件的特定的節裏(而且包含初始化的值),程序運行時也是直接將這個節加載到特定的段中,不必在程序運行期間用額外的代碼來產生這些變量。

其實在運行期間再看“變量”這個概念就不再具備編譯期間那麼多的屬性了(諸如名稱,類型,作用域,生存期等等),對應的只是一塊內存(只有首址和大小),所以在運行期間動態申請的空間,是需要額外的代碼維護,以確保不同變量不會混用內存。比如寫new表示有一塊內存已經被佔用了,其它變量就不能再用它了; 寫delete表示這塊內存自由了,可以被其它變量使用了。(通常我們都是通過變量來使用內存的,就編碼而言變量是給內存塊起了個名字,用以區分彼此)

內存申請和釋放時機很重要,過早會丟失數據,過遲會耗費內存。特定情況下編譯器可以幫我們完成這項複雜的工作(增加額外的代碼維護內存空間,實現申請和釋放)。從這個意義上講,局部自動變量也是由編譯器負責分配空間的。進一步講,內存管理用到了我們常常掛在嘴邊的堆和棧這兩種數據結構。

最後對於“編譯器分配空間”這種不嚴謹的說法,你可以理解成編譯期間它爲你規劃好了這些變量的內存使用方案,這個方案寫到可執行文件裏面了(該文件中包含若干並非出自你大腦衍生的代碼),直到程序運行時才真正拿出來執行!

 

~~~~~~~~~~~~~~


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章