您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“C語言中數據怎么存儲進內存”,內容詳細,步驟清晰,細節處理妥當,希望這篇“C語言中數據怎么存儲進內存”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
大家肯定經常聽說內存這個詞,內存到底是什么呢? 在計算機中,進程都要加載進內存中,也是我們各種數據的流通途徑,C語言中,大家肯定都知道指針變量,指針變量中保存的就是內存的地址,那么,什么是內存的地址呢?
內存的單位是字節
對于32位的機器,有32根地址線,每根地址線在尋址時,產生的高低電壓分別為0/1,那么32根地址線產生的地址就會是
00000000000000000000000000000000
00000000000000000000000000000001
00000000000000000000000000000010
…
11111111111111111111111111111111
這里就有2^32次方個地址
大家應該知道,還有64位的機器,64根地址線又有多少個地址呢,大家可以計算一下
在32位的機器上,地址是32個0或者1組成二進制序列,那地址就得用4個字節的空間來存儲,
所以一個指針變量的大小就應該是4個字節。 那如果在64位機器上,有64個地址線,那一個指針變量的大小是8個字節,才能存放一個地址。
這串編號就是內存單元的地址,就像酒店的房間號一樣,對應著內存中的一個字節大小的房間
我們在vs中來看一下
這里是以十六進制的方式展示的,大家也知道,32個數字看起來太長了。
關于c語言中的數據類型,大家在寫了這么多代碼后肯定也很清楚了,C語言中有整型、浮點型、字符型、等等
我們來研究一下整數在內存中是如何存儲的
大家都知道,定義變量,會在內存中開辟空間來存儲
int a = 20;
int類型在vs中占據4個字節的空間,那么如何存儲呢?
這就涉及到原碼反碼補碼的概念
計算機中的整數有三種2進制表示方法,即原碼、反碼和補碼。
三種表示方法均有符號位和數值位兩部分,符號位都是用0表示“正”,用1表示“負”,剩下數值位
正數的原、反、補碼都相同。
負整數的三種表示方法各不相同。
原碼:
直接將數值按照正負數的形式翻譯成二進制就可以得到原碼
反碼:
將原碼的符號位不變,其他位依次按位取反就可以得到反碼
補碼:
反碼+1就得到補碼。
對于整型變量來說,內存中存放的其實是補碼
使用補碼,可以將符號位和數值域統一處理,加法和減法也可以同一處理,因為CPU只有加法器
eg:
int a = 20; //原碼 : 直接寫二進制 00000000000000000000000000010100 //反碼--補碼 -- 正數的原反補相同 int b = -5; //原碼: 10000000000000000000000000000101 //反碼:符號位不變,按位取反 // 11111111111111111111111111111010 //補碼:反碼+1 // 11111111111111111111111111111011 -- -5的補碼
上邊可以看見-5的補碼是11111111111111111111111111111011 ,我們如何確認呢?
轉換成16進制為fffffffb
大家可以看到確實是使用補碼存儲的,但是為什么是倒著存儲的,后邊再來說,這是由于大小端的問題
給大家舉幾個例子,不知道存儲無法分析出結果代碼
//1. #include <stdio.h> int main() { char a = -128; printf("%u\n",a); //-128 原碼: 10000000 00000000 00000000 10000000 //-128 反碼: 11111111 11111111 11111111 01111111 //-128 補碼: 11111111 11111111 11111111 10000000 //存在a里面的,因為只有一個字節 10000000 //所以會當做無符號整數打印 --整形提升 //提升為 11111111111111111111111110000000 //所以結果是一個很大的整數,大家可以嘗試一下 return 0; }
#include <stdio.h> int main() { char a = 128; //128的原碼反碼補碼 : 00000000000000000000000010000000 //存在a里的:10000000 //整形提升 :11111111111111111111111110000000 //所以結果還是那個很大的整數 printf("%u\n",a); return 0;
例子就簡單給大家舉到這里,大家一定要記住整數在內存中是以補碼的形式存儲的
字符存儲的是ASCII碼,所以和整數同
我們來看一下浮點數在內存中的存儲
拋磚引玉:
#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("num的值為:%d\n",n); printf("*pFloat的值為:%f\n",*pFloat); return 0; }
上面代碼的打印結果到底是什么呢?
是不是非常出乎大家的意料呢,這里就可以看出,浮點數的存儲肯定和整數是不同的。那浮點數到底咋存的呢?
根據國際標準IEEE(電氣和電子工程協會) 754,任意一個二進制浮點數V可以表示成下面的形式:
(-1)^S * M * 2^E
(-1)^S表示符號位,當S=0,V為正數;當S=1,V為負數。
M表示有效數字,大于等于1,小于2。
2^E表示指數位。
看得很迷糊,直接上例子
v = 5.5
= 101.1 --二進制表示
= 1.011 * 2 ^2 – 科學記數法表示
因為是正數 s = 0
m = 1.011
e = 2
IEEE 754規定:
對于32位的浮點數,最高的1位是符號位s,接著的8位是指數E,剩下的23位為有效數字M。
IEEE 754對有效數字M和指數E,還有一些特別規定
1=<M <2 ,所以M可以寫成1.xxxxx 所以可以舍去1 ,只存儲xxxxxx
IEEE 754規定,在計算機內部保存M時,默認這個數的第一位總是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的時候,只保存01,等到讀取的時候,再把第一位的1加上去。這樣做的目的,是節省1位有效數字。以32位浮點數為例,留給M只有23位,將第一位的1舍去以后,等于可以保存24位有效數字
對于指數E,E是一個無符號整數,但是科學記數法指數是可以出現負數的,所以
IEEE 754規定了偏移量,如果E為8位,則加上127 ,如果E為11位,則加上1023
我們舉個例子
float f = 8.5f;
//二進制 : 1001.1
//科學計數法表示: 1.0011*2^3
//S = 0 M = 1.0011 E = 3
//存儲進去的應該是:
0 10000010 00110000000000000000000
//我們可以驗證一下
轉換成16進制
0100 0001 0001 1000 0000 0000 0000 0000
//41 18 00 00
我們來看一下代碼
和我們想的一樣
我們再來舉一個負數的例子
float t = -3.5f;
//二進制: 11.1
//科學記數法: 1.11*2^1
//S = 1 M = 1.11 E = 1
//存儲:
1 10000000 11000000000000000000000
//轉換成16進制
1100 0000 0011 0000 0000 0000 0000 0000
c0 60 00 00
那我們從內存中讀取出來的二進制位如何解析成浮點數呢
關于E,有三種情況
E不全為0或不全為1
這時,浮點數就采用下面的規則表示,即指數E的計算值減去127(或1023),得到真實值,再將有效數字M前加上第一位的1
2.E全為0
這時,浮點數的指數E等于1-127(或者1-1023)即為真實值,
有效數字M不再加上第一位的1,而是還原為0.xxxxxx的小數。這樣做是為了表示±0,以及接近于 0的很小的數字。
3.E全為1
這時,如果有效數字M全為0,表示±無窮大(正負取決于符號位s);
我們來分析一下最開始的題目
浮點數和整數的存儲就介紹到這里了,有哪里不清楚的朋友可以私信我
上邊有一個懸念,為什么是倒序存儲的
那什么是大端小端呢?
大端(存儲)模式: 數據的低位存儲在內存的高地址中,數據的高位存儲在內存的低地址中
小端(存儲)模式: 數據的低位存儲在內存的低地址中,數據的高位存儲在內存的高地址中
那為什么會有大小端呢?
內存中以字節為單位,但是比如int 是4個字節,那如何安排這個4個字節呢?就導致了大小端存儲模式
例如:一個 16bit 的 short 型 x ,在內存中的地址為 0x0010 , x 的值為 0x1122 ,那么 0x11 為高字節, 0x22 為低字節。對于大端模式,就將 0x11 放在低地址中,即 0x0010 中, 0x22 放在高地址中,即 0x0011 中。小端模式,剛好相反。我們常用的 X86 結構是小端模式,而 KEIL C51 則 為大端模式。很多的ARM,DSP都為小端模式。有些ARM處理器還可以由硬件來選擇是大端模式 還是小端模式。
那我們如何測試當前電腦是哪種存儲模式呢?
int main(void) { int a = 0x11223344; return 0; }
我們調試打開內存看一下
很明顯,數據的低位存儲在內存低地址中,所以為小端存儲模式。
我們能不能寫一個程序,直接告訴我們大小端呢?
我們來分析一下
我們來看一下代碼
int decide_byte_orde() { int i = 1; return *(char *)&i; }
我們來測試一下
讀到這里,這篇“C語言中數據怎么存儲進內存”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。