欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:C語言詳解(數(shù)據(jù)存儲)

柚子快報邀請碼778899分享:C語言詳解(數(shù)據(jù)存儲)

http://yzkb.51969.com/

????????Hi~!這里是奮斗的小羊,很榮幸各位能閱讀我的文章,誠請評論指點,歡迎歡迎~~? ? ?

?????????????????????????????????????????????????個人主頁:小羊在奮斗

?????????????????????????????????????????????????所屬專欄:C語言? ?

????????本系列文章為個人學(xué)習(xí)筆記,在這里撰寫成文一為鞏固知識,二為一些學(xué)友們展示一下我的學(xué)習(xí)過程及理解。文筆、排版拙劣,望見諒。?

????????????????????????????????1、大小端字節(jié)序和字節(jié)序判斷

????????????????????????????????2、浮點數(shù)在內(nèi)存中的存儲

????????????????????????????????????????????????2.1浮點數(shù)存的過程

????????????????????????????????????????????????2.2浮點數(shù)取的過程

1、大小端字節(jié)序和字節(jié)序判斷

? ? ? ? 在?C語言(操作符)1?中,我們介紹了整數(shù)在內(nèi)存中的存儲,但是我們只介紹了整數(shù)的存儲形式,并沒有介紹整數(shù)是如何存儲的,那本節(jié)我們就來探討一下整數(shù)在內(nèi)存中究竟是怎么存儲的。

? ? ? ? 當(dāng)我們想把0x11223344這個數(shù)存到一個整型變量a中時,因為整型數(shù)據(jù)的大小是4個字節(jié),以字節(jié)為單位存儲,那么11占一個字節(jié),22占一個字節(jié),33占一個字節(jié),44占一個字節(jié),假設(shè)從低地址向高地址存儲,那先存11還是先存44就是一個問題。其實超過一個字節(jié)的數(shù)據(jù)在內(nèi)存中存儲的時候,就有存儲順序的問題,按照不同的存儲順序,我們分為大端字節(jié)序存儲和小端字節(jié)序存儲。

? ? ? ? 也就是說,大端字節(jié)序存儲是地址由低到高依次存高位,小端字節(jié)序存儲是地址由低到高依次存低位。

? ? ? ? ?我們之前可能會疑惑VS中整數(shù)在內(nèi)存中為什么是反著存的,那這里就給了我們解釋,VS所在的當(dāng)前計算機系統(tǒng)使用的是小端字節(jié)序存儲,而大多數(shù)計算機架構(gòu)使用的都是小端字節(jié)序存儲。

? ? ? ? 如果我們想知道當(dāng)前的機器使用的是哪種存儲方式,可以寫一個簡單的判斷小程序來實現(xiàn)。當(dāng)我們在一個整型變量中存一個整數(shù)1時,如果當(dāng)前機器是大端字節(jié)序存儲,那么它存的就是? ? ? ? ?00 00 00 01,如果當(dāng)前機器是小端字節(jié)序存儲,那么它存的就是 01 00 00 00。既然如此,我們只需要將這個整型變量最小字節(jié)中的數(shù)據(jù)拿出來,看這個最小字節(jié)單元中存的數(shù)是0還是1,如果是0就是大端字節(jié)序存儲,反之則為小端字節(jié)序存儲。

? ? ? ? 了解了大小端存儲,我們來做一些練習(xí)加深理解。

? ? ? ? 練習(xí)1?

? ? ? ? 上面代碼的輸出結(jié)果是什么呢?(其實我們在C語言(操作符)2中的表達式求值部分已經(jīng)學(xué)習(xí)過)我們來分析一下:

? ? ? ? 我們想將整數(shù)-1存入一個字符型變量a中,整型和字符型不兼容,通過C語言(操作符)2的學(xué)習(xí)我們知道要發(fā)生截斷,所以只將-1的補碼的后8位存到a中,我們又用%d(打印有符號整型)打印字符型變量a,那%d就認為它打印的數(shù)是整型,a不是整型所以要發(fā)生整型提升,a是char(signed char)類型,整型提升高位補符號位,補完后還是32個1,取反加一得原碼又變?yōu)榱?1,最終結(jié)果就打印出了-1,因為在VS中char和signed char是一樣的,所以打印b也就同樣的道理。

? ? ? ? 而我們將整數(shù)-1存入一個無符號字符型變量c中,截斷只存入-1的補碼的后8位,用%d打印需要整型提升,而c是無符號字符型,整型提升高位補0,補完后用%d打印時%d看它就是一個比較大的正數(shù),原反補相同,00000000000000000000000011111111就是255。

? ? ? ? 練習(xí)2?

? ? ? ? 將整數(shù)-128(補碼:11111111111111111111111110000000)存入(signed)char類型a中,截斷后a中存的是10000000,用%u(打印無符號整數(shù))打印需要整型提升,a為signed char所以高位補符號位,補完就是11111111111111111111111110000000,目前還是補碼,但是在%u眼中無符號整形原反補相同,所以%u再以原碼打印出來就是4294967168。

? ? ? ? 將a改為128,結(jié)果還是一樣的,因為它們截斷的結(jié)果是一樣的。

? ? ? ? 至于為什么對a存-128還是128結(jié)果是一樣的,這里再做一個解釋:

? ? ? ? 我們很早就知道,(signed)char類型的取值范圍是:-128~127?,但是為什么是這個范圍并沒有解釋。char類型占一個字節(jié)也就是8個比特位,最高位當(dāng)做符號位來看待,就剩下了7位存0、1值。

? ? ? ? 在C語言(操作符)2中,我們還畫了這樣一個圖,并做了相應(yīng)解釋。

? ? ? ? 127+1在數(shù)學(xué)上是128,但在char類型中就是-128,因為char類型最大的正數(shù)就是127,所以給char類型存128和-128是一樣的。其他的類型都是這樣的道理。

? ? ? ? 練習(xí)3?

?

? ? ? ? 創(chuàng)建一個字符數(shù)組大小1000,向數(shù)組中存入-1、-2、-3..,然后strlen求字符數(shù)組a的長度。我們知道strlen是求字符串的長度,統(tǒng)計的是\0之前的字符個數(shù),那看來意思就是讓我們找字符‘\0’了又因為a是字符數(shù)組所以-1、-2、..、-127、-128、127、126、...、2、1、0,0在字符眼中就是\0,所以求的是-1~0的長度,是255。

?

? ? ? ? 練習(xí)4?

? ? ? ? unsigned char的范圍是0~255,所以上面的代碼給我們的感覺就是打印255個hello world,但事實真是如此嗎?當(dāng)我們運行起來就會發(fā)現(xiàn)程序陷入了死循環(huán)。這是因為當(dāng)i加到256時雖然此時不滿足循環(huán)了,但是這時候的256只是數(shù)學(xué)上的256,而在unsigned char眼中255+1就變成了0,所以循環(huán)繼續(xù)。

? ? ? ? 上面這個代碼也是如此,當(dāng)i為0時,0-1就變成了2^32-1,因為在unsigned int的世界里沒有負數(shù),所以程序陷入了死循環(huán)。

? ? ? ? 練習(xí)5

? ? ? ? 創(chuàng)建一個整型數(shù)組大小4,&a取出整個數(shù)組的地址再+1跳過整個數(shù)組指向數(shù)組末尾,此時指針(地址)的類型是int (*) [4],再強轉(zhuǎn)為 int * 類型的指針賦給ptr1,ptr1[-1]( *(ptr -1) )就是int *類型的指針-1向后推4個字節(jié)指向數(shù)組最后一個元素4,再解引用用%x(打印16進制)打印出來就是4。

? ? ? ? 數(shù)組名a表示數(shù)組首元素的地址,強轉(zhuǎn)為int類型的整數(shù)再+1,再強轉(zhuǎn)為int *類型的指針,最終的結(jié)果就是數(shù)組首元素的地址+1(整數(shù)+1),注意ptr2是一個整型類型的指針,所以它訪問的是4個字節(jié)的地址。

?

? ? ? ? 我們又知道小端字節(jié)序是反著存的,所以ptr2指向的數(shù)值就是02 00 00 00,打印出來就是2000000。

? ? ? ? 如果我們想把代表16進制的0x也打印出來,可以在%的后面加上#。

2、浮點數(shù)在內(nèi)存中的存儲

? ? ? ? 2.1浮點數(shù)存的過程

? ? ? ? 浮點數(shù)和整數(shù)在內(nèi)存中的存儲有什么區(qū)別嗎?

? ? ? ? 如果用我們學(xué)到的整數(shù)存儲的方法來解讀上面的代碼,打印出來的結(jié)果應(yīng)該就是9、9.000000、9、9.000000。

? ? ? ? 但結(jié)果并不是這樣,通過觀察我們發(fā)現(xiàn),只有當(dāng)n是整數(shù)9時用%d打印的結(jié)果和當(dāng)n是浮點數(shù)9.0時用%f打印的結(jié)果是我們預(yù)料中的,所以可以肯定的是整數(shù)和浮點數(shù)在內(nèi)存中的存儲是不一樣的。

? ? ? ? 那浮點數(shù)在內(nèi)存中是怎么存的呢?根據(jù) IEEE 754規(guī)定,任意一個二進制浮點數(shù)V可以表示為這樣的形式:V=(-1)^S*M*2^E。(-1)^S表示符號位,當(dāng)S=0,V為正數(shù);當(dāng)S=1,V為負數(shù)。M表示有效數(shù)字,M是大于等于1小于2的。2^E表示指數(shù)位。

? ? ? ? 比如十進制的5.5,寫成二進制就是101.1,轉(zhuǎn)化的方法是按位權(quán)來轉(zhuǎn)化,小數(shù)點前面的位權(quán)是2的1次方、2的2次方、2的3次方....,小數(shù)點后面的位權(quán)是2的-1次方、2的-2次方、2的-3次方......。十進制的5.5二進制表示101.1用科學(xué)計數(shù)法表示就是1.011*2^2,又因為5.5是正數(shù),所以用IEEE 754標(biāo)準(zhǔn)表示就是:(-1)^0*1.011*2^2。其中的S=0,M=1.011,E=2。

? ? ? ? 任何一個浮點數(shù)都可以用S、M、E這三個值來表示,所以浮點數(shù)的存儲,存儲的就是S、M、E 相關(guān)的值。

? ? ? ? IEEE 754規(guī)定:

? ? ? ? 對于32位的浮點數(shù)(float),最高的1位存儲符號位S,接著的8位存儲指數(shù)E,剩下的23位存儲有效數(shù)字M。

?????????對于64位的浮點數(shù)(double),最高的1位存儲符號位S,接著的11位存儲指數(shù)E,剩下的52位存儲有效數(shù)字M。

? ? ? ? IEEE 754對有效數(shù)字M和指數(shù)E還有一些特別規(guī)定。?

? ? ? ? 前面說過,1<=M<=2,所以M總是1.xxxxx,IEEE 754規(guī)定,在計算機內(nèi)部保存M時,默認這個數(shù)的第一位是1,因此1可以舍去,只保存小數(shù)點后面的xxxxx,讀取的時候再把第一位的1加上就行。這樣做的目的是節(jié)省1位有效數(shù)字,使存儲的精度更高。?

? ? ? ? E作為一個無符號整數(shù),如果E為8位,它的取值范圍是0~255;如果E為11位,它的取值范圍是0~2047。但是在科學(xué)計數(shù)法中指數(shù)有可能是負數(shù),所以 IEEE 754規(guī)定,存入內(nèi)部的E的真實值必須再加上一個中間數(shù),對8位的E這個中間數(shù)是127;對11位的E這個數(shù)是1023。比如2^10的E是10,保存成32位的浮點數(shù)時,必須保存成137,即10001001。我們也不用擔(dān)心加上這個中間數(shù)后E的值還不能為正數(shù),因為當(dāng)E非常小時已經(jīng)無限接近于0了,而float和double也是有精度限度的。

? ? ? ? 比如float類型的5.5在內(nèi)存中的存儲就是:

?

? ? ? ? 本計算機系統(tǒng)采用的是小端字節(jié)序存儲。?

? ? ? ? 2.2浮點數(shù)取的過程

? ? ? ? 指數(shù)E從內(nèi)存中取出的過程可分為三種情況:

? ? ? ? E不全為0或不全為1(常規(guī)情況)

? ? ? ? 指數(shù)E的計算值減去127或1023得到真實值,再將有效數(shù)字M前加上第一位的1。

? ? ? ? E全為0(罕見)

? ? ? ? 這時,浮點數(shù)的指數(shù)E等于1-127或1-1023即為真實值,有效數(shù)字M不再加上第一位的1,而是還原為0.xxxxx的小數(shù)。這樣做是為了表示+-0,以及無限接近于0的極小的數(shù)字。

? ? ? ?E全為1(罕見)

? ? ? ? 這時,E的真實值為255-127=128,這又是一個極大的數(shù),大到我們無法想象,所以就不去討論它了。

? ? ? ? 了解清楚了浮點數(shù)在內(nèi)存中的存取后,我們再來分析一下前面的那個代碼。

? ? ? ? 創(chuàng)建一個整型變量n賦值為9,用%d打印時就按常規(guī)打印出整數(shù)9。我們再取出n的地址將其強轉(zhuǎn)為float *類型的指針再賦給pfloat,再解引用pfloat用%f打印,9在內(nèi)存中的補碼是:

00000000000000000000000000001001,而pfloat是float *類型的指針,所以pfloat就認為它指向的數(shù)是一個浮點數(shù),就會按浮點數(shù)存取的規(guī)則來讀取,在pfloat眼中整數(shù)9的補碼是這個樣子:

? ? ? ? S=0,E為全0,那這個值就是一個極小的正數(shù),無限接近于0,而float只能打印小數(shù)點后6位,所以打印的結(jié)果應(yīng)該就是0.000000。

? ? ? ? 而將9.0存到float *類型的地址中時,9.0用二進制表示為:1001.0,根據(jù) IEEE 754 規(guī)定,S=0,M=1.001,E=3,那在內(nèi)存中的存儲就應(yīng)該是下面這個樣子的:

? ? ? ? 用%d打印時%d就認為這是一個很大的正數(shù) ,原反補相同。而用%f打印就是正常的9.000000。

? ? ? ? 本節(jié)內(nèi)容并不需要我們死記硬背,只需要知道整數(shù)和浮點數(shù)在底層是怎么存取的,又有什么差異,當(dāng)某天我們錯用格式符打印不同類型的值時,我們要知道是怎么回事,要會分析,為什么會輸出這個值,這個值是隨機的還是有它的道理的就行。

? ? ? ? 只要我們遵守規(guī)則,有符號整數(shù)就用%d打印,無符號整數(shù)就用%u打印,float類型就用%f打印,double類型就用%lf打印,size_t類型就用%zd打印……就行。

?????????如果覺得我的文章還不錯,請點贊、收藏 + 關(guān)注支持一下,我會持續(xù)更新更好的文章。??

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? 點擊跳轉(zhuǎn)下一節(jié) —>?C語言(結(jié)構(gòu)體)

柚子快報邀請碼778899分享:C語言詳解(數(shù)據(jù)存儲)

http://yzkb.51969.com/

精彩文章

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://m.gantiao.com.cn/post/19523659.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄