計算機存儲和讀取數據的最小單位是字節、再每個字節編上唯一的編號后大概便是下面的樣子。
我們常說的內存地址,就是指數據在內存中的內存編號。按照編號查找某個數據在內存單元中的位置,稱為尋址。
對於操作系統,他保留了一段內存區域以供操作系統來使用,其它程序不允許使用這個內存。----在上圖中用 黃色標記。
對於程序來說,他們使用內存就是剩下的區域。
值類型變量:以變量名所對應的內存地址為起點,以其數據類型所要求的存儲空間為長度的一塊內存區域。
值類型變量在內存中是如何存儲的:
例子1:byte a; a=100;為例。
分析:
1、看到byte時,我們知道變量a占據一個字節的內存空間。
2、計算機去尋找內存中,哪里有空閑的存儲空間,則從此處分配內存空間。
3、a=100,100用二進制補碼表示時:01100 0100,存儲到分配給a的空余空間中。
所以,最終 10000007 就是變量a的內存地址。
例子2:以 sbyte b;b=-100;為例:
1、sbyte 是有符號的整型,最高位表示符號位,取值范圍從-128~+127;
2、我們知道計算機中存儲的數是以二進制補碼的形式存放的,-100的補碼:10011100
3、計算機會為變量b尋找到一個空余內存,並分配一字節的空間,並將10011100填充到這塊空間中
所以,變量b在內存中的存儲形式便是上圖,b變量的內存地址是 10000010
例子3:以ushort c=1000;為例:
1、ushort 兩個占據兩個字節的存儲空間,表示無符號整數
2、1000的二進制形式位:0000 0011 1110 1000
3、對於超過一個字節的變量,數據在內存中存儲的規則:高高低低原則--即:高位放在內存地址編號大的位置、低位放在內存地址編號小的位置。
所以,ushort類型變量c的內存地址是 1000 0016。
例子4:對於值類型數據,他們可以調用Convert.Tostring()方法,來快速求出二進制表示形式,解決了我們求類似-1000的補碼比較慢的問題。
short c = -1000; string s = Convert.ToString(c, 2); Console.WriteLine(s);
運行結果:1111 1100 0001 1000
引用類型變量:引用類型變量里面存儲的是實例的內存地址。
下面來看一下引用類型變量和引用類型實例在內存中的對應關系。
比如:在Main()方法中有下面一段代碼:Student student;student=new Student();已知Student類型中有兩個成員 int類型ID、short類型score;
1、當程序解析到 Student student時,判斷到student是引用類型的變量,那么分配內存的方式和值類型完全不同。
2、值類型變量是按照,變量的實際大小分配空間的,而引用類型變量直接會被分配四個字節的空間,並且初始值都設置為0(也就是null)。
3、當解析到student=new Student()時,分兩步操作,
- 第一步:相應new Student(),在堆內存中根據成員類型和個數分配相應大小的空間
- 第二部:將對象在堆內存中的其實內存地址的值轉換成二進制值,賦值給引用類型變量
經計算,30000009的二進制值是:00000001110010011100001110001001 按照高高低低原則,給student變量所占的內存區域賦值后。
4、最終student變量存儲的便是Student類型實例的內存地址,我們可以說,引用類型變量通過實例的地址指向了堆中了一個實例。
總結:
1、局部變量 (比如stundent、a、b、c等,都是在Mian方法中的) 在Stack上面分配內存
2、實例變量 (比如Student類型中的 ID、Score字段等) 在Heap上面分配內存
以上是對引用類型變量和值類型變量在內存中的存儲方式的總結,記錄下來,以便以后查閱。