C#:值型別變數和引用型別變數在記憶體中的儲存方式
值型別變數:以變數名所對應的記憶體地址為起點,以其資料型別所要求的儲存空間為長度的一塊記憶體區域。
計算機儲存和讀取資料的最小單位是位元組、再每個位元組編上唯一的編號後大概便是下面的樣子。
我們常說的記憶體地址,就是指資料在記憶體中的記憶體編號。按照編號查詢某個資料在記憶體單元中的位置,稱為定址。
對於作業系統,他保留了一段記憶體區域以供作業系統來使用,其它程式不允許使用這個記憶體。----在上圖中用 黃色標記。
對於程式來說,他們使用記憶體就是剩下的區域。
值型別變數在記憶體中是如何儲存的:
例子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。
3、當解析到student=new Student()時,分兩步操作,
- 第一步:相應new Student(),在堆記憶體中根據成員型別和個數分配相應大小的空間
- 第二部:將物件在堆記憶體中的其實記憶體地址的值轉換成二進位制值,賦值給引用型別變數
經計算,30000009的二進位制值是:00000001110010011100001110001001 按照高高低低原則,給student變數所佔的記憶體區域賦值後。
4、最終student變數儲存的便是Student型別例項的記憶體地址,我們可以說,引用型別變數通過例項的地址指向了堆中了一個例項。
總結:
1、區域性變數 比如stundent、a、b、c等,都是在Mian方法中的 他們是在Stack上面分配記憶體的
2、例項變數 比如Student型別中的 ID、Score欄位等,他們是在Heap上面分配記憶體的
以上是對引用型別變數和值型別變數在記憶體中的儲存方式的總結,記錄下來,以便以後查閱。