大家都直到,在c語言中有很多的資料型別,基本的內建型別有char,short,int long,long long,float,double,這些內建的型別可以分為整形家族和浮點數家族。而我們常用的也就是這兩種型別,這回就深度解析一下整形和浮點型在記憶體中的儲存。
我們知道,定義乙個變數在記憶體中是需要開闢空間對這個變數進行儲存的,不同的型別所佔的空間大小也不一樣。那麼整形資料在記憶體中是如何儲存的呢?
在詳細討論之前要先了解乙個知識,就是原碼、反碼、補碼的概念。
1.原碼
原碼是直接將十進位制數按照正負數的形式轉化為二進位制即可。
比如:-20的原碼是10000000000000000000000000010100
其最高位代表的是符號位,用「0」表示「正」,用「1」表示「負」
2.反碼
反碼是原碼的符號位即最高位不變,其他位按位取反即可。
比如: - 20的反碼是11111111111111111111111111101011
3.補碼是反碼+1就可以得到補碼
比如: -20的補碼是11111111111111111111111111101100
這就是原碼、反碼、補碼的基本概念。這裡要注意:正數的原碼、反碼、補碼都是相同的。
+10的原碼、反碼、補碼都是00000000000000000000000000001010
這裡為什麼要提這個概念呢,因為對於整形的資料來說,在記憶體中存放的是資料轉換為二進位制後的補碼。
舉乙個例子:
定義兩個變數a、b,a=20,b=-10
a=20為正數,其原碼、反碼、補碼是相同的,也就是說,a=20在記憶體中直接轉換成二進位制進行儲存。
用十六進製制表示也就是0x00000014
在編譯器除錯的記憶體視窗來進行要驗證
發現果然是0x00000014
b也是如此,但是不同的是,b=-10是乙個負數,存進去的時候是需要轉化的。
用編譯器進行除錯:
和我們算的一樣,是0xfffffff6
這就說明了,整形的變數在記憶體中確實是以二進位制的補碼形式進行儲存的。
細心的同學就會發現,為什麼在記憶體裡的順序和我們算出來的是不一樣的。這就涉及到乙個知識點,就是大小端儲存的問題。在不同的機器中是不一樣的。
大端(儲存)模式:是指資料的低位儲存在記憶體的高位址中,而資料的高位,儲存在記憶體的低位址中。
小端(儲存)模式:是指資料的低位儲存在記憶體的低位址中,而資料的高位,,儲存在記憶體的高位址中。
在0x ff ff ff f6中,f6是低位,ff是高位
在記憶體中,從左至右的位址是由高到低
因此由儲存的方式可以看出來,一般我們用的電腦都是小端儲存模式
這裡有一道曾經的面試題,考的就是大小端儲存的問題。
題目是要求寫乙個程式,判斷當前機器的位元組序。其實思路非常簡單,拿乙個數算出這個數的補碼,檢視儲存這個數的記憶體低位址存放的是這個數的低位還是高位即可。最簡單的就是用1去測試。
#include
intcheck_sys()
intmain()
else
return0;
}
通過char* 取出的值和1位與,如果是0則是大端,是1則是小端。
說完了整形,就要說浮點數了,它在記憶體中的儲存與整形是完全不同的,通過乙個**就可以看出一點端倪。
用浮點數來列印乙個整形是0.000000,而用整形列印乙個浮點數竟然是乙個很大的數,這究竟是為什麼呢?
這就說明浮點數在記憶體中的儲存和整形是不同的,那麼浮點數是怎麼儲存的呢?
根據國際標準 ieee754,任意乙個二進位制浮點數v可以表示位下面的形式:
(-1)^s * m * 2^e
其中:(-1)^s表示符號位,當s=0,v為正數;當s=1,v為負數。
m表示有效數字,大於等於1,小於2。
2^e表示指數字。
比如說:十進位制的9.5,寫成二進位制是1001.1,相當於1.0011*2^3,按照上面的格式,s=0,m=1.0011,e=3。
ieee 754規定:對於32位的浮點數,最高的1位是符號位s,接著的8位是指數e,剩下的23位為有效數字m。對於64位的浮點數,最高的1位是符號位s,接著的11位是指數e,剩下的52位為有效數字m。
除了這些之外,還有一些特別的規定:
1.m是1≤m<2的,在內部儲存m時,所有的數預設第一位是1,因此可以被捨去,只儲存1後面的小數點部分,這樣做是為了節省一位有效數字,提高精度。在拿出這個浮點數時再把1加上。
2.對於指數e,e是乙個無符號整數,但是科學計數法中,e是可以出現負數的。那麼ieee 754就規定存入記憶體時e的真實值必須再加上乙個中間數,對於8位的e,這個中間數是127;對於11位的e,這個中間數是1023。這就保證了所有的指數都是正數。比如,2^10的e是10,所以儲存成32位浮點數時,必須儲存成10+127=137,即10001001。
3.取出指數e的時候,分為三種情況:
第一種:e不全位0或者不全為1,這是最基本的情況。
第二種:e全為0,這時的e的真實值是1-127,而2^(1-127)是乙個非常小的數字,此時表示正負0。
第三種:e為全1,此時e的真實值是255-127=128,而2^128次方是乙個很大的數,此時表示正負無窮。
這就是浮點數再記憶體中的儲存方式,那麼來解釋一下為什麼會出現上面的結果?
對於整數9來說,在記憶體中存的是補碼,但是用浮點數的方式拿出來的時候,就會按照浮點數的方式來進行解讀
此時m是00000000000000000001001,而e是全0,也就是-126,這時列印出來的就是0.000000。
對於浮點數來說,在記憶體中是按照浮點數的方式進行儲存的,但是用整形的方式拿出來的時候就會按照整形的方式進行解讀。
這就是為什麼列印出來的結果截然不同的原因。
以上就是整形和浮點數在記憶體中的儲存方式。
深度解析資料在記憶體中的儲存
整形家族 char 字元資料型別 short 短整形 int 整形 long 長整形 long long 更長的整形 浮點數家族 float 單精度浮點數 double 雙精度浮點型 它們的大小決定了使用範圍,根據不同的型別開闢相應的記憶體空間。構造型別 1.陣列型別 2.結構體型別 struct ...
資料在記憶體中的儲存
身為乙個天天處理資料的人,不得不說資料在記憶體中的儲存是必須要知道的問題。首先,資料在記憶體中的儲存涉及到作用域,儲存位置等方面的問題。根據資料的作用域,可將資料劃分為區域性變數和全域性變數 區域性變數的作用域為從定義開始到函式執行結束 全域性變數的作用域從程式開始到程式結束。計算機的記憶體分配可以...
資料在記憶體中的儲存
大端,把乙個數字高位位元組序的內容儲存到低位址,低位位元組序內容儲存到高位址處 小端,把乙個數字高位位元組序的內容儲存到高位址,低位位元組序內容儲存到低位址處 判斷乙個機器是大端還是小端?指標判斷 int checksys 聯合體 共用體 union un int main 這裡首先需要知道的是,例...