?? 作者:阿輝不一般
?? 你說呢:生活本來沉悶,但跑起來就有風(fēng)
?? 專欄:愛上C語言
??作圖工具:draw.io(免費(fèi)開源的作圖網(wǎng)站)
如果覺得文章對(duì)你有幫助的話,還請(qǐng)點(diǎn)贊,關(guān)注,收藏支持博主,如有不足還請(qǐng)指點(diǎn),博主及時(shí)改正,感謝大家支持?。?!
??前言
大家好啊??!今天阿輝將為大家介紹C語言中整型和浮點(diǎn)型在內(nèi)存中的存儲(chǔ)的,?包括進(jìn)制轉(zhuǎn)換,原碼,反碼,補(bǔ)碼以及大小端,接下來還會(huì)介紹關(guān)于原反補(bǔ)碼的相關(guān)例題關(guān)注阿輝不迷路哦 ?? ,內(nèi)容干貨滿滿??,接下來就跟著阿輝一起學(xué)習(xí)吧??
??數(shù)據(jù)類型
- 整型
char
unsigned char——無符號(hào)
signed char——有符號(hào)
short
unsigned short [int]
signed short [int]
int
unsigned int
signed int
long
unsigned long [int]
signed long [int]
long long
大家可能會(huì)疑惑
char
不是字符類型嗎?
因?yàn)樽址趦?nèi)存是以ASCII值
存儲(chǔ)的所以也可以劃分到整型
- 浮點(diǎn)型
float 單精度浮點(diǎn)型
double 雙精度浮點(diǎn)型
- 構(gòu)造類型
數(shù)組類型
結(jié)構(gòu)體類型 struct
枚舉類型 enum
聯(lián)合類型 union
- 指針類型
int * ip;
char * cp;
float * fp;
void * vp;
空類型:void 表示空類型(無類型)通常應(yīng)用于函數(shù)的返回類型、函數(shù)的參數(shù)、指針類型
數(shù)據(jù)的類型決定了內(nèi)存為所存數(shù)據(jù)開辟空間的大小,以及數(shù)據(jù)是如何存進(jìn)內(nèi)存中又是如何從內(nèi)存中取出的
給一個(gè)類型比如int
和float
我們知道它倆都在內(nèi)存中占4個(gè)字節(jié)
那它倆創(chuàng)建的變量的數(shù)據(jù)在所開辟內(nèi)存中到底是如何存儲(chǔ)的
??整型在內(nèi)存中的存儲(chǔ)
??進(jìn)制的轉(zhuǎn)換
C語言規(guī)定表示八進(jìn)制數(shù)要前面加個(gè)數(shù)字0
,表示十六進(jìn)制數(shù)要在前面加0x
而十進(jìn)制數(shù)什么都不用加就表示十進(jìn)制數(shù)
十進(jìn)制轉(zhuǎn)二進(jìn)制:
二進(jìn)制轉(zhuǎn)八進(jìn)制:
8進(jìn)制的數(shù)字每?位是0 ~ 7,0~7的數(shù)字,各自寫成2進(jìn)制,最多有3個(gè)2進(jìn)制位就足夠了,比如7的二進(jìn)制是111,所以在2進(jìn)制轉(zhuǎn)8進(jìn)制數(shù)的時(shí)候,從2進(jìn)制序列中右邊低位開始向左每3個(gè)2進(jìn)制位會(huì)換算一個(gè)8進(jìn)制位,剩余不夠3個(gè)2進(jìn)制位的直接換算
??栗子
2進(jìn)制的01101011,換成8進(jìn)制:0153,0開頭的數(shù)字,會(huì)被當(dāng)做8進(jìn)制
二進(jìn)制轉(zhuǎn)十六進(jìn)制:
16進(jìn)制的數(shù)字每?位是0~ 9,a ~ f 的,0~9,a ~f的數(shù)字,各自寫成2進(jìn)制,最多有4個(gè)2進(jìn)制位就足夠了,比如 f 的二進(jìn)制是1111,所以在2進(jìn)制轉(zhuǎn)16進(jìn)制數(shù)的時(shí)候,從2進(jìn)制序列中右邊低位開始向左每4個(gè)2進(jìn)制位會(huì)換算?個(gè)16進(jìn)制位,剩余不夠4個(gè)二進(jìn)制位的直接換算。
十六進(jìn)制中10~15用a,b,c,d,e,f
表示
??栗子
2進(jìn)制的01101011,換成16進(jìn)制:0x6b,16進(jìn)制表示的時(shí)候前?加0x
整形在內(nèi)存中都是以補(bǔ)碼的形式來存儲(chǔ)的,什么補(bǔ)碼是什么?
我們接著看??
??原碼、反碼和補(bǔ)碼
符號(hào)位就是二進(jìn)制數(shù)的最高位,符號(hào)位為1
該數(shù)為負(fù)數(shù),為0
該數(shù)為正數(shù)
正數(shù)的原反補(bǔ)碼相同
而負(fù)數(shù)的原反補(bǔ)碼需要按以下方式計(jì)算:
-
原碼
直接將數(shù)值按照正負(fù)數(shù)的形式翻譯成二進(jìn)制就可以得到原碼 -
反碼
將原碼的符號(hào)位不變,其他位依次按位取反就可以得到反碼 -
補(bǔ)碼
反碼+1就得到補(bǔ)碼
由補(bǔ)碼得到原碼同樣可以將補(bǔ)碼的符號(hào)位不變,其他位依次按位取反就可以然后
+1
就得到原碼
這里我們以整型中最常見的int
為例,為大家介紹整型在內(nèi)存中是如何存儲(chǔ)的int
占4個(gè)字節(jié)也就是32個(gè)比特位
??栗子
int a = 20;
0000 0000 0000 0000 0000 0000 0001 0100 -> 原碼
0000 0000 0000 0000 0000 0000 0001 0100 -> 反碼
0000 0000 0000 0000 0000 0000 0001 0100 -> 補(bǔ)碼
0x 00 00 00 14 -> 20的補(bǔ)碼十六進(jìn)制表示
int b = -10;
1000 0000 0000 0000 0000 0000 0000 1010 ->原碼
1111 1111 1111 1111 1111 1111 1111 0101 ->反碼//原碼符號(hào)位不變,其他位按位取反
1111 1111 1111 1111 1111 1111 1111 0110 ->補(bǔ)碼//反碼+1
0xff ff ff ff f6 -> -1的補(bǔ)碼十六進(jìn)制表示
整型是以二進(jìn)制形式在內(nèi)存中存儲(chǔ),但是二進(jìn)制數(shù)太長不好展示,在vs2022環(huán)境中調(diào)試內(nèi)存是以十六進(jìn)制來展示的(以下圖片均來自vs2022x86環(huán)境下調(diào)試結(jié)果)
對(duì)于正數(shù)的存儲(chǔ)我們并不能得到內(nèi)存是以補(bǔ)碼來存儲(chǔ)整型,我們來看看負(fù)數(shù)
通過上面的演示我們知道整型在內(nèi)存中是以二進(jìn)制形式的補(bǔ)碼來存儲(chǔ)的,這是為什么呢?
原因在于,使?補(bǔ)碼,可以將符號(hào)位和數(shù)值域統(tǒng)?處理;
同時(shí),加法和減法也可以統(tǒng)?處理(CPU只有加法器)此外,補(bǔ)碼與原碼相互轉(zhuǎn)換,其運(yùn)算過程是
相同的,不需要額外的硬件電路
但是你們有沒有發(fā)現(xiàn)在內(nèi)存中這些數(shù)字是倒著存的
這是為什么呢?我們接著往下↓看
??大小端字節(jié)序
我們了解了整型在內(nèi)存中的存儲(chǔ),但是呢卻是倒著存的,我們來看看??
??栗子
#include <stdio.h>
int main()
{
int a = 0x11223344; 十六進(jìn)制數(shù)便于觀察
return 0;
}
這就得提一個(gè)重要的概念就是大小端??
什么是大小端?
其實(shí)超過一個(gè)字節(jié)的數(shù)據(jù)在內(nèi)存中存儲(chǔ)的時(shí)候,就有存儲(chǔ)順序的問題,按照不同的存儲(chǔ)順序,我們分為大端字節(jié)序存儲(chǔ)和小端字節(jié)序存儲(chǔ),下面是具體的概念:
什么是字節(jié)序呢,就是以字節(jié)為單位進(jìn)行排序,每個(gè)字節(jié)為一個(gè)整體
大端(存儲(chǔ))模式:是指數(shù)據(jù)的低位字節(jié)內(nèi)容保存在內(nèi)存的高地址處,而數(shù)據(jù)的高位位字節(jié)內(nèi)容,保存在內(nèi)存的低地址處。
小端(存儲(chǔ))模式:是指數(shù)據(jù)的低位字節(jié)內(nèi)容保存在內(nèi)存的低地址處,而數(shù)據(jù)的高位字節(jié)內(nèi)容,保存在內(nèi)存的高地址處
從上圖我們可以知道vs2022為小端模式
為什么會(huì)有大小端呢?
這是因?yàn)樵谟?jì)算機(jī)系統(tǒng)中,我們是以字節(jié)為單位的,每個(gè)地址單元都對(duì)應(yīng)著?個(gè)字節(jié),?個(gè)字節(jié)為8bit 位,但是在C語?中除了8 bit 的 char 之外,還有16 bit 的 short 型,32 bit 的 long 型(要看具體的編譯器),另外,對(duì)于位數(shù)大于8位的處理器,例如16位或者32位的處理器,由于寄存器寬度大于一個(gè)字節(jié),那么必然存在著?個(gè)如何將多個(gè)字節(jié)安排的問題。因此就導(dǎo)致了大端存儲(chǔ)模式和小端存儲(chǔ)模式
那么如何利用一個(gè)簡(jiǎn)單的代碼來判斷當(dāng)前機(jī)器是什么字節(jié)序呢,我們接著看??
#include <stdio.h>
int check_sys()//封裝一個(gè)函數(shù)判斷當(dāng)前機(jī)器為何種模式
{
int i = 1;
數(shù)字1為int類型有4個(gè)字節(jié)補(bǔ)碼為
0000 0000 0000 0000 0000 0000 0000 0001
如果是小端模式它的低地址第一個(gè)字節(jié)是0000 0001
如果是大端模式它的低地址第一個(gè)字節(jié)是0000 0000
return (*(char *)&i);
而將&i強(qiáng)制轉(zhuǎn)化為char*類型后,對(duì)&i解引用操作僅能訪問一個(gè)字節(jié)
如果是小端模式那返回值就是1
如果是大端模式那返回值就是0
}
int main()
{
int ret = check_sys();
if(ret == 1)
{
printf("?端\n");
}
else
{
printf("?端\n");
}
return 0;
}
上述我通過int
類型來介紹了大小端,但并非只有int
類型要用大小端字節(jié)序來存儲(chǔ),只要是空間大于一個(gè)字節(jié)都會(huì)用大小端字節(jié)序來存儲(chǔ)包括整型以及浮點(diǎn)型
??浮點(diǎn)型在內(nèi)存中的存儲(chǔ)
浮點(diǎn)型包括float
double
long double
,那么浮點(diǎn)型又是如何存儲(chǔ)的呢,是否與整型相同呢?我們接著看??
??浮點(diǎn)型的存儲(chǔ)規(guī)則
根據(jù)國際標(biāo)準(zhǔn)IEEE(電氣和電子工程協(xié)會(huì)) 754,任意一個(gè)二進(jìn)制浮點(diǎn)數(shù)V可以表示成下面的形式:
- ( ? 1 ) S ? M ? 2 E (-1)^{S}*M*2^{E} (?1)S?M?2E
- ( ? 1 ) S (-1)^{S} (?1)S表示符號(hào)位,S為1表示負(fù)數(shù),S為0表示正數(shù)
- M M M表示有效數(shù)字, M M M的值大于等于1,小于2
- 2 E 2^{E} 2E表示指數(shù)位
有點(diǎn)懵,沒關(guān)系我舉個(gè)??栗子
比如一個(gè)浮點(diǎn)數(shù) 5.0f
5.0用二進(jìn)制表示就是101.0
而101.0 = (-1)^0 * 1.01 * 2^2//這里(-1)^0表示-1的0次方,*表示乘號(hào)
而S = 0,M = 1.01,E = 2
而 -5.0f
就可以表示為(-1)^1 * 1.01 * 2^2
S = 1,M = 1.01,E = 2
IEEE 754規(guī)定:
對(duì)于32位的浮點(diǎn)數(shù)也就是float
類型,最高的1位是符號(hào)位S,接著的8位是指數(shù)E,剩下的23位為有效數(shù)字M
對(duì)于64位的浮點(diǎn)數(shù),最高的1位是符號(hào)位S,接著的11位是指數(shù)E,剩下的52位為有效數(shù)字M
IEEE 754對(duì)有效數(shù)字M和指數(shù)E,還有一些特別規(guī)定。
前面說過, 1≤M<2 ,也就是說,M可以寫成 1.xxxxxx 的形式,其中xxxxxx表示小數(shù)部分。
IEEE 754規(guī)定,在計(jì)算機(jī)內(nèi)部保存M時(shí),默認(rèn)這個(gè)數(shù)的第一位總是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.11的時(shí)候,只保存11,等到讀取的時(shí)候,再把第一位的1加上去。這樣做的目的,是節(jié)省1位有效數(shù)字。以32位浮點(diǎn)數(shù)為例,留給M只有23位,將第一位的1舍去以后,等于可以保存24位有效數(shù)字。
至于指數(shù)E,情況就比較復(fù)雜。首先,E為一個(gè)無符號(hào)整數(shù)(unsigned int)
這意味著,如果E為8位,它的取值范圍為0 ~ 255;如果E為11位,它的取值范圍為0 ~2047。但是,我們知道,科學(xué)計(jì)數(shù)法中的E是可以出現(xiàn)負(fù)數(shù)的,所以IEEE 754規(guī)定,存入內(nèi)存時(shí)E的真實(shí)值必須再加上一個(gè)中間數(shù),對(duì)于8位的E,這個(gè)中間數(shù)是127;對(duì)于11位的E,這個(gè)中間
數(shù)是1023。比如,2^10的E是10,所以保存成32位浮點(diǎn)數(shù)時(shí),必須保存成10+127=137,即10001001
??栗子
float f = 5.5f;
它的二進(jìn)制表示101.1//0.5是2的-1次方
也等于(-1)^0 * 1.011 * 2^2
其中S = 0,M = 1.011,E = 2 + 127 = 129
129的二進(jìn)制表示10000001
但是存在一些浮點(diǎn)數(shù)是無法表示出來的。小數(shù)點(diǎn)后面的數(shù)無法完整地表示出來,可能總是差一點(diǎn)點(diǎn)。可能會(huì)出現(xiàn)精度的缺失
以上我們了解了浮點(diǎn)數(shù)是如何存入內(nèi)存中的,那我們?nèi)绾稳〕鰜砟兀课覀兘又??
??浮點(diǎn)數(shù)的讀取規(guī)則
這里分為三種情況:文章來源:http://www.zghlxwxcb.cn/news/detail-754795.html
-
E中有1有0時(shí):
這時(shí),浮點(diǎn)數(shù)就遵循以下規(guī)則:
指數(shù)E的存儲(chǔ)值減去127(或1023),有效值M前補(bǔ)數(shù)字1
??栗子 -
E中全為0時(shí):
這時(shí),浮點(diǎn)數(shù)的指數(shù)E等于1-127(或者1-1023)即為真實(shí)值,有效數(shù)字M不再加上第一位的1,而是還原為0.xxxxxx的小數(shù)。這樣做是為了表示±0,以及接近于0的很小的數(shù)字 -
E中全為1時(shí)
這時(shí),如果有效數(shù)字M全為0,表示±無窮大(正負(fù)取決于符號(hào)位s)
到這里,阿輝今天對(duì)于C語言中整型以及浮點(diǎn)型在內(nèi)存中的存儲(chǔ)的分享就結(jié)束了,希望這篇博客能讓大家有所收獲, 如果覺得阿輝寫得不錯(cuò)的話,記得給個(gè)贊唄,你們的支持是我創(chuàng)作的最大動(dòng)力??文章來源地址http://www.zghlxwxcb.cn/news/detail-754795.html
到了這里,關(guān)于愛上C語言:整型和浮點(diǎn)型在內(nèi)存中的存儲(chǔ)(進(jìn)制轉(zhuǎn)換,原碼,反碼,補(bǔ)碼以及大小端)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!