摘要:在符號位中,表示正,表示負(fù)。我們知道對于整型來說,內(nèi)存中存放的是該數(shù)的補(bǔ)碼。在計算機(jī)系統(tǒng)中,數(shù)值一律用補(bǔ)碼來表示和存儲。表示有效數(shù)字,。規(guī)定對于位的浮點(diǎn)數(shù),最高的位是
最近博主開學(xué)啦!更新節(jié)奏有點(diǎn)跟不上,這里做個檢討~
UU們開學(xué)感覺怎么樣呢?見到同學(xué)或者舍友有沒有很開心呢?又可以一起愉快地玩耍咯!
但是玩歸玩,學(xué)習(xí)還是正事,話不多說,開始今天的內(nèi)容。
在之前的內(nèi)容中,我們已經(jīng)把C語言的入門知識進(jìn)行了一個全面的講解,并介紹了一些實(shí)用的調(diào)試技巧,以及函數(shù)棧幀的創(chuàng)建和銷毀,可以說對于C語言已經(jīng)算是敲過開門磚了。
那么今天,我們就要開啟深入學(xué)習(xí)C語言的旅程啦!首先解決C語言進(jìn)階第一問:數(shù)據(jù)在內(nèi)存中是如何存儲的?
當(dāng)然,我們主要探討的是整型和浮點(diǎn)型這兩種類型。
C語言中具以下幾種基本內(nèi)置類型:
這里說明一下:
- C語言的基本內(nèi)置類型只的是C語言本身具有的類型,而庫函數(shù)本身是不屬于C語言的,是獨(dú)立于C語言之外的。
- C語言是用來決定語言的語法形式的,而庫函數(shù)是編譯器的產(chǎn)商提供,當(dāng)然庫函數(shù)的使用是受C語言標(biāo)準(zhǔn)約束的(比如C語言標(biāo)準(zhǔn)規(guī)定了一些庫函數(shù)的函數(shù)名、參數(shù)類型、返回值類型和函數(shù)功能)。
- 這樣做的好處是雖然不同編譯器實(shí)現(xiàn)函數(shù)的方式不一樣,但是對于我們來說,在不同的編譯器下使用函數(shù)的方式是一樣的。
- 當(dāng)然在有一些編譯器中對一些庫函數(shù)的支持提供得不是很好,比如在VS編譯器下使用scanf函數(shù)就可能會報錯,需要使用scanf_s。
由于字符類型在存儲的時候是按照ASCII碼值存儲的,所以字符類型也屬于整型家族中的一員。
前面我們已經(jīng)學(xué)習(xí)了以上這么多的數(shù)據(jù)類型,并且了解了它們所占內(nèi)存空間的大小。
我們還要明白,我們?yōu)槭裁匆o數(shù)據(jù)分那么多的類型:
- 我們生活中出了的數(shù)除了整數(shù)就是小數(shù),所以為了更好地存儲這兩種類型,數(shù)據(jù)分為整型和浮點(diǎn)型兩大類
- 使用不同的類型時內(nèi)存開辟的空間大小是不一樣的(使用范圍也不一樣)。我們應(yīng)該根據(jù)數(shù)據(jù)的大小選擇合適的類型,如果選大了,則浪費(fèi)空間;選小了,則數(shù)據(jù)無法完整存儲。
- 不同類型決定了我們看待空間時應(yīng)該采用哪種視角。即對于內(nèi)存中不同空間的類型存和取的方式是不一樣的。
- char
unsigned char
signed char- short
unsigned short [int]
signed short [int]- int
unsigned int
signed int- long
unsigned long [int]
signed long [int]
-long long
unsigned long long [int]
signed long long [int]
注意:
如何理解有符號和無符號:
以char類型舉例:
這里也說明了不同類型決定了我們看待內(nèi)存中的值時視角也不同。
同時,我們也可以由此推算出一個類型中最大能放一個多大的數(shù)字。
還是以char類型舉例:
由此可以得出,有符號的char中可以存放的數(shù)的范圍是 -128 ~ 127。
相同道理:
無符號的char中可以存放的數(shù)的范圍是 0 ~ 255。
同理,我們可以得出short、int 、long等等類型的范圍。
float
double
這兩種類型通常根據(jù)數(shù)據(jù)要求的精度來選擇:精度高選擇double類型(8個字節(jié)),精度低選擇float類型(4個字節(jié))。
一般我們更常選擇float類型,但是記住噢~3.14默認(rèn)是double類型哦!
除了內(nèi)置類型之外,還有構(gòu)造類型,即可以自己創(chuàng)造的類型。
數(shù)組類型
結(jié)構(gòu)體類型 struct
枚舉類型 enum
聯(lián)合類型 union
數(shù)組類型為什么也屬于構(gòu)造類型呢?
我們來看看數(shù)組的類型:
當(dāng)我們定義的數(shù)組元素的類型和個數(shù)不同時,數(shù)組的類型也不同,可以通過sizeof反映出來,所以我們也說數(shù)組屬于構(gòu)造類型。
int *pi
char *pc
float *pf
void *pv
void表示空類型(即無類型)
常用于函數(shù)的返回類型、函數(shù)參數(shù)和指針類型
這里說void作為函數(shù)參數(shù)是什么情況呢?
正常我們在調(diào)用函數(shù)的時候,如果這個函數(shù)不需要傳參,則不寫參數(shù)。
但是如果是一個不需要傳參的函數(shù),而我們又給它傳參了,函數(shù)會怎樣呢?在有的編譯器中,會報錯,但是有的編譯器則會接受這種情況。
但是如果我們給參數(shù)加上一個void。編譯器就會報錯或者警告,告訴你不能傳參啦!
我們知道,一個變量創(chuàng)建之后是要在內(nèi)存中開辟空間的,那么這些變量在內(nèi)存中到底是怎么存儲的呢?
接下來我們就來看看~
首先看看整型在內(nèi)存中是如何存儲的。
我們知道,二進(jìn)制中有符號的整數(shù)有原碼、反碼、補(bǔ)碼三種表示方式。
這三種表示方式都有符號位和數(shù)值位兩部分。
- 在符號位中,0表示“正”,1表示“負(fù)”。
- 在數(shù)值位中,正數(shù)的原、反、補(bǔ)碼相同;負(fù)數(shù)的三種表示方法各不相同:
原碼:直接將二進(jìn)制按照正負(fù)數(shù)的形式翻譯成二進(jìn)制。
反碼:將原碼的符號位不變,其他位依次按位取反。
補(bǔ)碼:反碼+1得到補(bǔ)碼。
我們知道對于整型來說,內(nèi)存中存放的是該數(shù)的補(bǔ)碼。
在計算機(jī)系統(tǒng)中,數(shù)值一律用補(bǔ)碼來表示和存儲。
但是存放的是補(bǔ)碼,而不是原碼或者反碼呢?
因?yàn)椋褂醚a(bǔ)碼可以將符號位和數(shù)值位作統(tǒng)一處理。
同時,加法和減法也可以統(tǒng)一處理(CPU只有加法器)。
因此,補(bǔ)碼與原碼相互轉(zhuǎn)換,其運(yùn)算過程是相同的,不需要額外的硬件電路。
比如,我們想計算1-1。但是因?yàn)镃UP只有加法運(yùn)算,所以我們可以把表達(dá)式寫成1+(-1)。
我們可以看到,用原碼計算,得不出正確的結(jié)果。
但是如果用補(bǔ)碼計算,情況就不一樣了。
從上圖的計算中,我們可以看出,使用補(bǔ)碼可以直接對符號位和數(shù)值位同一進(jìn)行處理。
這里有一個有意思的事情:
我們知道原碼、反碼和補(bǔ)碼都是怎么得到的,那么計算一下我們會發(fā)現(xiàn)用同樣的方法,我們也可以通過補(bǔ)碼得到原碼。
(不信你試著算一下!)
所以,由此我們可以看到用補(bǔ)碼來存儲的好處。
我們看到,a是一個十六進(jìn)制的數(shù),當(dāng)我們在內(nèi)存中查看它的存儲情況時,可以發(fā)現(xiàn),它的存放是從低地址開始放44 33 22 11。
對于它們在內(nèi)存中的存放順序,其實(shí)可以有很多種存放的方式。
但是如果大家都按照自己的想法來寫,則整個存儲就會亂套,而且如果我們不按照正常的順序存儲時,取出來要獲得原來的數(shù)就比較麻煩,所以我們最后決定只以下兩種存儲順序。
注意:這里的存儲順序是以字節(jié)為單位來討論的。因此,也稱字節(jié)序。
其中,上面的存儲順序稱為小端字節(jié)序;下面的存儲順序稱為大端字節(jié)序。
- 小端字節(jié)序存儲
把一個數(shù)的低位字節(jié)的內(nèi)容,存儲在內(nèi)存的低地址出,把這個數(shù)的高位字節(jié)的內(nèi)容,存儲在內(nèi)存的高地址處。- 大端字節(jié)序存儲
把一個數(shù)的低位字節(jié)的內(nèi)容,存儲在內(nèi)存的高地址出,把這個數(shù)的高位字節(jié)的內(nèi)容,存儲在內(nèi)存的低地址處。
那么,為什么在存儲時還要有大小端之分呢?
這是因?yàn)樵谟嬎銠C(jī)系統(tǒng)中,內(nèi)存空間的最小單元是一個字節(jié)。所以,如果我們存放的變量大小大于一個字節(jié)時,我們就不得考慮每個字節(jié)應(yīng)該以何種順序存放在內(nèi)存中了。
那么我們當(dāng)前的編譯器是采取大端存儲還是小端存儲呢?
別著急,回頭看看內(nèi)存中的值的順序,就能知道啦!
所以,我們當(dāng)前編譯器采用的是小端字節(jié)序。
百度曾經(jīng)出過一道筆試題,讓被試者設(shè)計一個程序來判斷當(dāng)前機(jī)器的字節(jié)序。
那么我們應(yīng)該如何做呢?
我們用1來進(jìn)行觀察。
所以,我們只需要拿出第一個字節(jié),看看里面存的是0還是1就知道了。
當(dāng)然,我們要實(shí)現(xiàn)的是查看一個機(jī)器字節(jié)序的功能,所以這里我們最好把程序封裝成一個函數(shù)。
看完了整數(shù)在內(nèi)存中是怎么存儲的,那么浮點(diǎn)型在內(nèi)存中又是怎么存儲的呢?
我們接下來就來看看。
首先我們常見的浮點(diǎn)數(shù)有:
小數(shù):3.1425926
科學(xué)計數(shù)法:1E10(1.0*1010)
在浮點(diǎn)型中,我們有float和double兩種類型。
而這兩種類型的范圍,我們用float.h來定義。
如果我們想看整數(shù)的最大值(最小值),我們就用INT_MAX(INT_MIN);并在前面包含頭文件
。
然后我們就能看到int類型所能存放的最大值啦!
那么,浮點(diǎn)數(shù)所能存放的最大最小值是多少呢?
同理,我們可以用FLT_MAX(或者FLT_MIN、DBL_MAX等),引用頭文件
就能得到他們的精度啦~
那么在內(nèi)存中浮點(diǎn)數(shù)的存儲和整數(shù)的存儲是一樣的嗎?
我們可以先通過一段代碼來進(jìn)行驗(yàn)證。
那么如果浮點(diǎn)型的存儲和整型不一樣,它又是怎么存儲的呢?
根據(jù)國際標(biāo)準(zhǔn)IEEE(電氣和電子工程協(xié)會) 754,任意一個二進(jìn)制浮點(diǎn)數(shù)V可以表示成下面的形式:
- (-1)S * M * 2E
(-1)s表示符號位,當(dāng)S=0,V為正數(shù);當(dāng)S=1,V為負(fù)數(shù)。
M表示有效數(shù)字,1≤M<2。
2E表示指數(shù)位。
我們以小數(shù)5.5來舉例。
同理,我們可以寫出9.0的表示形式:
我們會發(fā)現(xiàn),其實(shí)任何一個浮點(diǎn)數(shù)都可以寫成這種形式。
那么,只要我們把一個浮點(diǎn)數(shù)寫成(-1)S * M * 2E這種形式,那么只要我們存儲了S、M、E的信息,就能還原出浮點(diǎn)數(shù)的值了。
IEEE 754規(guī)定: 對于32位的浮點(diǎn)數(shù),最高的1位是符號位S,接著的8位是指數(shù)E,剩下的23位為有效數(shù)字M。
對于64位的浮點(diǎn)數(shù),最高的1位為符號位S,接著是11位的指數(shù)E,剩下的52位為有效數(shù)字M。
因?yàn)?≤M<2 即M可以寫成1.XXXXXX 的形式,其中XXXXXX表示小數(shù)部分。
IEEE 754規(guī)定,在計算機(jī)內(nèi)部保存M時,默認(rèn)這個數(shù)的第一位總是1,因此這個1和它后面的小數(shù)點(diǎn)可以被舍去,只保存后面的XXXXXX部分。
比如:當(dāng)我們要保存1.01的時候,只需要保存01,等到讀取的時候,再把前面的1.加上去。
這樣,我們就節(jié)省了1位有效數(shù)字。
以32位浮點(diǎn)數(shù)(float)為例,留給M只有23位,將第一位的1舍去以后,等于可以保存24位有效數(shù)字,這樣精度就得到了提高。
我們知道,對于指數(shù)E來說,它是可以去負(fù)數(shù)的,那么對于負(fù)數(shù)的E在存儲的時候,我們又應(yīng)該如何處理呢?
于是人們又想出了一個辦法,不如給這個E加上一個中間數(shù),讓E即使是最小的負(fù)數(shù),加上這個數(shù)之后也不會為負(fù)(等于0),那么就不會出現(xiàn)負(fù)數(shù)的情況了,只要我們?nèi)〕鰜淼臅r候再把這個中間數(shù)加上就行了。
這樣,我們就可以把E作為一個無符號整數(shù)了。
如果E為8位,那么它的取值范圍就是:0~255,那么它的中間數(shù)就是127。
對于11位的E,它的取值范圍是0~2047,它的中間數(shù)就是1023。
比如:210的E是10,所以保存成32位浮點(diǎn)數(shù)時,就保存成10+127=137,即10001001。
以5.5為例,我們可以在內(nèi)存中看到它的存儲。
并且我們可以發(fā)現(xiàn),對于浮點(diǎn)數(shù),它在內(nèi)存中的存儲也是有大小端的。
以上,我們就知道了浮點(diǎn)數(shù)在內(nèi)存中是怎么存的了。
那么它又是怎么取出來的呢?
按道理,我們是怎么放進(jìn)去的,就應(yīng)該是怎么取出來的。但是由于指數(shù)E比較特別,所以再取出來時,又有一些特別的規(guī)定。
在內(nèi)存中取出E時,我們有一下三種情況:
E不全為0或不全為1
這時,E是怎么存進(jìn)來的,我們就按照原路取出來。
即指數(shù)E的計算值減去127(或1023),得到真實(shí)值,再將有效數(shù)字M前加上第一位的1。
比如: 0.5的二進(jìn)制形式為0.1,由于規(guī)定正數(shù)部分必須為1,即將小數(shù)點(diǎn)右移1位,則為1.0*2^(-1)。
同理,反過來,我們可以通過這個二進(jìn)制序列得到0.5。
E全為0
當(dāng)E全為0的時候,說明浮點(diǎn)數(shù)的指數(shù)E等于-127,而2-127是一個非常非常小的數(shù),已經(jīng)十分接近于0了。
所以這時候,我們就不再按照原來的計算方式,而是把浮點(diǎn)數(shù)的指數(shù)E直接記為1-127(或者1-1023), 并且有效數(shù)字M不再加上第一位的1,而是還原為0.XXXXXX的小數(shù)。這樣做是為了表示±0,以及無窮接近于0的很小的數(shù)。
E全為1
當(dāng)E全為1時,則得到的是255,減去127得到的是128,而2128是一個非常大的數(shù)。所以這時,如果有效數(shù)字M全為0,則該數(shù)就表示±無窮大(正負(fù)取決于符號位S)
當(dāng)我們了解完以上浮點(diǎn)型在內(nèi)存中的存儲規(guī)則之后,我們就可以理解之前哪個代碼打印出來的值了。
今天的文章就到這里啦!~
你學(xué)廢了嗎?記得點(diǎn)贊收藏加關(guān)注,在評論區(qū)留下你的腳印~
關(guān)注我!一起精進(jìn)C語言!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/119293.html
摘要:結(jié)構(gòu)體類型的特殊聲明在初階結(jié)構(gòu)體中,我們已經(jīng)將了結(jié)構(gòu)體類型是如何進(jìn)行聲明的,那么在這里,我們將講一些特殊的結(jié)構(gòu)體聲明不完全的聲明。所以我們應(yīng)該這樣寫通過指針來找到下一個同類型結(jié)構(gòu)體的寫法,我們就稱之為結(jié)構(gòu)體的自引用。 ...
摘要:插件開發(fā)前端掘金作者原文地址譯者插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡單的方式。提供了與使用掌控異步前端掘金教你使用在行代碼內(nèi)優(yōu)雅的實(shí)現(xiàn)文件分片斷點(diǎn)續(xù)傳。 Vue.js 插件開發(fā) - 前端 - 掘金作者:Joshua Bemenderfer原文地址: creating-custom-plugins譯者:jeneser Vue.js插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡單的方式。插....
摘要:的理解和區(qū)別代表有符號,整數(shù)在內(nèi)存中存儲的二進(jìn)制位的最高位為符號位,表示負(fù)數(shù),表示正數(shù)。那接下來我們來學(xué)習(xí)數(shù)據(jù)在所開辟的內(nèi)存空間時如何存儲的。請看下面例子為什么內(nèi)存中存儲的是補(bǔ)碼對于整數(shù)來說數(shù)據(jù)存放內(nèi)存中其實(shí)存放的是補(bǔ)碼。 ...
摘要:中的詳解必修個多線程問題總結(jié)個多線程問題總結(jié)有哪些源代碼看了后讓你收獲很多,代碼思維和能力有較大的提升有哪些源代碼看了后讓你收獲很多,代碼思維和能力有較大的提升開源的運(yùn)行原理從虛擬機(jī)工作流程看運(yùn)行原理。 自己實(shí)現(xiàn)集合框架 (三): 單鏈表的實(shí)現(xiàn) 自己實(shí)現(xiàn)集合框架 (三): 單鏈表的實(shí)現(xiàn) 基于 POI 封裝 ExcelUtil 精簡的 Excel 導(dǎo)入導(dǎo)出 由于 poi 本身只是針對于 ...
閱讀 1438·2023-04-25 16:31
閱讀 2040·2021-11-24 10:33
閱讀 2743·2021-09-23 11:33
閱讀 2528·2021-09-23 11:31
閱讀 2900·2021-09-08 09:45
閱讀 2336·2021-09-06 15:02
閱讀 2646·2019-08-30 14:21
閱讀 2312·2019-08-30 12:56