C語言中數據的存儲詳解
數據的存儲首先就要說到數據的類型,類型決定瞭看待內存空間的視角。
C語言的數據類型分為內置類型和外置類型
1.內置類型
(1)整型數組
char
(字符型)、short
(短整型)、int
(整型)、long
(長整型)(signed
或者 unsigned
)
(2)浮點型
float
(單精度浮點型)、double
(雙精度浮點型)
2.自定義類型
(1)數組類型
此處需要註意的是,去掉數組名就是數組的類型
比如int arr[10],去掉數組名arr,int [10]就是數組數據類型
(2)結構體類型(struct
)
(3)枚舉類型(enum
)
(4)聯合類型(union
)
3.指針類型
4.空類型(void)
數據的存儲形式就是以計算機的原碼反碼補碼進行存儲的
浮點型:不以原反補的形式進行存儲
其他的數字又分為有符號數和無符號數
無符號數:無符號數的原反補三種碼是一致的,存儲的時候沒有區別
符號數來:正數的原反補碼是相同的,但是負數的原反補碼需要經過運算轉化(正數的最高位是0,負數的最高位是1)
原碼:將二進制按照正負數形式翻譯為二進制數字
反碼:將原碼的每一位取反
補碼:反碼+1
存儲的時候一般存儲數字的二進制序列補碼
同時數據的存儲存在大小端
內存空間具有編號,編號小的為低地址,編號大的為高地址
大端存儲:數據的低位保存在內存的高地址中
小端存儲:數據的低位保存在內存的低地址中
每個機器的存儲方式不同,可以用如下一段簡單代碼來觀察電腦是哪一種存儲方式
#include<stdio.h> int main() { int a = 1; char* p = (char*)&a; //此處將整型地址強制轉化為字符型 //強制轉化並不影響地址的存儲,隻會影響讀取 //指針決定讀取內存的位數,字符型指針在解引用時隻解1字節,整型指針在解引用時解4字節 //a存儲時,a是正數,原反補相同 //00000000 00000000 00000000 00000001 //指針在強制轉化為字符型之後隻能讀取該內存的前8位 //如果該指針解引用後結果是1,該數據存儲結果為00000001 00000000 00000000 00000000 //如果不是,該數據存儲結果為00000000 00000000 00000000 00000001 if (*p == 1) { printf("小端\n"); } else { printf("大端\n"); } return 0; }
字符型
char/signed char 所對應的存儲區間為-128~127,同時規定10000000為-128。
為瞭理解signed與unsigned,適用如下例題
#include<stdio.h> int main() { unsigned int i; for (i = 9; i >= 0; i--) //在這個循環開始之前就需要註意到,i需要小於0,該循環才會停止 //但是此時的i是一個unsigned類型,本身存儲的時候並沒有預留符號位,是沒有辦法破開循環的 //該循環是死循環 { printf("%d", i); } }
signed
與unsigned
的區別就在於能否表示正負數
在數據的存儲時,是否存在符號位
signed char與char類型的存儲也可以用一個圖來說明
中間的分界線即為正負分界線,第一位即為符號位。符號位為1是負數,符號位為0即為正數
理解char的存儲范圍,借用如下例題
#include<stdio.h> #include<string.h> int main() { char a[1000]; int i; for (i = 0; i < 1000; i++) { a[i] = -1 - i; } printf("%d", strlen(a)); return 0; } //i是int類型,可以隨著循環不斷增長,但是對於a這個數組來說,能存儲的數據有限。 //數組a是字符型,字符型數組能存儲的范圍就是-128~127之間,一共255個數,所以數組長度也是255
運行結果:255
int等類型的存儲方式與char相似,這裡就不在多做贅述
利用一個例子來證明浮點型存儲與整型存儲不同
#include<stdio.h> int main() { int n = 9; float* pfloat = (float*)&n; printf("n的值為:%d\n", n); printf("*pfloat的值為:%f\n", *pfloat); //此處以單精度浮點型的指針取出存儲在整形中的數據 *pfloat = 9.0; printf("n的值為:%d\n", n); printf("*pfloat的值為:%f\n", *pfloat); //此處通過單精度浮點型的指針更改原本存儲在整型中的數字,並將其更改為單精度浮點型數字 return 0; }
輸出結果:
n的值為:9
*pfloat的值為:0.000000
n的值為:1091567616
*pfloat的值為:9.000000
由此可見,單精度浮點型的指針並不能成功取出原本存儲在整形中的數字,而第二步中通過單精度浮點型的指針所更改的整形的值,n也無法成功取用,所打出來的數字並不是9。由此可見二者的存儲方式是存在較大差異的,所以下面對浮點型的存儲方式進行講解。
浮點型
浮點型並不依靠數據的原反補碼進行存儲
浮點型有其特殊的規定
(E也可以理解為最高此項所對應的階次)
用實例來證明一下
比如8.5這個浮點數
轉化為二進制
1000.1
對於這個數而言,存儲成圖中形式就是
(-1)^0*1.0001*2^3
存儲就是
0 00000011 00000000000000000010001
此時假設我們所申請到的內存是一個條狀,那麼對於浮點數而言的數據存儲方式如圖所示
單精度浮點型對應的就是圖一中所示,SME分佈在不同的位置,圖二的所示為雙精度浮點型,雙精度與單精度浮點型所對應的E與M不同。
(一)
就是E的值,既不能全為0,也不能全為1,且E的存儲值與真實值不相同
為瞭表示極小的小數,比如1*10^-10,因為E本身不具有符號位,所以不能表示負數
單精度:E=真實值+127
雙精度:E=真實值+1023
加完之後再轉化為二進制存儲為E,拿出來使用的時候再將這個數字減去
特殊情況1:E為全0
單精度的E此時的真實值為-127,該浮點數幾乎等於0,是一個幾乎不存在的數字
特殊情況2:E為全1
單精度的E此時的真實值為128,該浮點數是為正負無窮大的數字
(二)
對於M來說,M的值既然是在區間【1,2)之間,則位於整數部分的肯定為1
再次利用單精度浮點型存儲8.5
該數字的M為1.0001
為瞭能讓浮點數表達更大的數字,且M中處於個位的數字固定為1,之後就規定,M中個位的1可以不再進行存儲,等到取用的時候再進行添加。
總結
本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!