int、unsigned int、float、double 和 char 在内存中存储方式
零、基礎(chǔ)知識
原碼、反碼和補(bǔ)碼是計算機(jī)存儲數(shù)字的編碼方式(表示方法)。
拓展:ASCII 碼、utf-8 和 utf-16 是計算機(jī)存儲字符的編碼方式。
原碼:符號位+數(shù)值的絕對值。
(1)以 8 位為例,1 的原碼為 0000 0001,-1 的原碼為 1000 0001。
(2)取值范圍:11111111 ~ 01111111,即:-127 ~ 127。
反碼:正數(shù)的反碼是原碼,負(fù)數(shù)的反碼是在原碼的基礎(chǔ)上符號位不變,其他位取反的結(jié)果。
以8位為例:1的反碼為 0000 0001,-1的反碼為 1111 1110。
補(bǔ)碼:正數(shù)的補(bǔ)碼是原碼,負(fù)數(shù)的補(bǔ)碼是在原碼的基礎(chǔ)上符號位不變,其他位取反再加一,即:反碼+1。
以8位為例:1 的補(bǔ)碼為 0000 0001,-1 的補(bǔ)碼為 1111 1111。
補(bǔ)碼存在的意義
(1)1 - 1 = 1 + (-1) = (0000 0001)(原) + (1000 0001)(原) = (1000 0010)(原) = -2。錯誤
(2)3 + 5 = (0000 0011)(原) + (0000 0101)(原) = (0000 1000)(原) = 8。正確
(3)反碼相減:3 - 4 = (0000 0011)(原) + (1000 0100)(原) = (0000 0011)(反) + (1111 1011)(反) = (1111 1110)(反) = (1000 0001)(原) = -1。正確
(4)反碼相減:5 - 3 = (0000 0101)(原) + (1000 0011)(原) = (0000 0101)(反) + (1111 1100)(反) + 1(循環(huán)進(jìn)位)= (0000 0010)(反) = (0000 0010)(原) = 2。正確
(5)1 - 1 = 1 + (-1) = (0000 0001)(反) + (1111 1110)(反) = (1111 1111)(反) = (1000 0000) = -0。
(6)1 - 1 = (0000 0001)(原) + (1000 0001)(原) = (0000 0001)(補(bǔ)) + (1111 1111)(補(bǔ))= (0000 0000) (補(bǔ)) = (0000 0000) (原) = 0。
(7)-1-127 = (1000 0001)(原) + (1111 1111)(原) = (1111 1111)(補(bǔ)) + (1000 0001)(補(bǔ)) = (1000 0000)(補(bǔ)) = -128。
A、由(1)和(2)可知,原碼相加是正確的,但是相減是錯誤的。
B、由(3)和(4)可知,反碼相加減都是正確的。
C、但是由(5)可知,1-1 的反碼結(jié)果為 -0,這個結(jié)果在數(shù)學(xué)上是沒有意義的,為了解決這個問題,引入了補(bǔ)碼。因為補(bǔ)碼是在反碼的基礎(chǔ)上加 1,故補(bǔ)碼的加減是沒有問題的,關(guān)鍵是 1-1 了。由(6)可知,補(bǔ)碼完美的解決了 1-1 等于 -0 的尷尬局面,直接得到 0 。
D、由(7)可知,計算機(jī)底層算法規(guī)定了補(bǔ)碼 1000 0000 = -128。這也就導(dǎo)致了補(bǔ)碼的取值范圍由-127127變?yōu)?128127。
總結(jié):
(1)由于原碼相減結(jié)果不對,故使用了反碼。但是反碼1-1得到的結(jié)果是-0,這個在數(shù)學(xué)上是無意義的,為了導(dǎo)出 1-1=0 的正確結(jié)果,故使用了補(bǔ)碼,同時規(guī)定補(bǔ)碼1000 0000 = -128,從而可以將-0表示為 -128,拓展了一個表示位,故8位二進(jìn)制取值范圍為 -128~127 。
(2)這里再次強(qiáng)調(diào),在計算機(jī)中,數(shù)據(jù)都是以正數(shù)的補(bǔ)碼的形式存在的。正數(shù)的補(bǔ)碼是其本身,負(fù)數(shù)則是以其本身的正數(shù)的補(bǔ)碼的形式存在的。
栗子:-123 在計算機(jī)中的存儲的值是 1111 1011 -> 1000 0100 -> 1000 0101。
一、int
原因:0 代表 +0,-0 代表 -2^31,故負(fù)數(shù)比整數(shù)多一個。
二、unsigned int
三、float
(1)15.987 的整數(shù)部分原碼:1111。
(2)15.987 的小數(shù)部分原碼:11111100……此處省略 11 位。
拓展:小數(shù)二進(jìn)制的計算方法:乘 2 取整,順序排列。
栗:0.987 的二進(jìn)制的計算過程如下:0.9872 = 1.974,則第一位為“1”,0.9742 = 1.948,第二位為“1”,0.948*2 = 1.896,,第三位為“1”,依次類推,直至結(jié)果的小數(shù)為0。當(dāng)然肯定有無窮盡的,這種情況就是計算機(jī)存儲浮點數(shù)的精度的問題了。所以,只有讓整數(shù)部分和小數(shù)部分的位數(shù)和為 24 位(隱藏位技術(shù))即可。此栗中,小數(shù)精度為 20 位。
(3)經(jīng)過上述計算,15.987的二進(jìn)制為1111.11111100……,用科學(xué)計數(shù)法表示為1.11111111100……*2^3。
(4)指數(shù)部分采用移位存儲的方式,即3+(2^7-1) = 130。其二進(jìn)制:10000010。
(5)尾數(shù)部分省略科學(xué)計數(shù)法的整數(shù)部分!!(因為肯定是1)(隱藏位)
(6)15.987在內(nèi)存中的存放的內(nèi)容為:
符號位:0(共 1 位)。
指數(shù)部分:10000010(共 8 位)。
尾數(shù)部分:111111111000……(共 23 位)。
(7)寫成完整的二進(jìn)制:0100 0001 0111 1111 1100 0……
(8)寫成16進(jìn)制:41 7F C……。
(9)因為Intel的架構(gòu)的字節(jié)序是小端序,則真正的存放內(nèi)容為……C 7F 41。
四、double
原理同上!
五、char
代碼中字符是“1”,ASCII碼為 49,轉(zhuǎn)換為 16 進(jìn)制為 31。
六、拓展
在存儲浮點數(shù)時,若指數(shù)部分若不使用移位存儲技術(shù),則會導(dǎo)致 0 有兩種表示方式:1000 000 0 和 0000 000 0。所以,為了最大化利用價值,同時保留正負(fù)性,在原數(shù)據(jù)的基礎(chǔ)上加 127,其結(jié)果如下:
0000 000 0~0111 111 1代表著-127~0。
1000 000 0~1111 111 1代表著1~127。
這樣正負(fù)指數(shù)均可表示的數(shù)量保持一致。
(SAW:Game Over!)
總結(jié)
以上是生活随笔為你收集整理的int、unsigned int、float、double 和 char 在内存中存储方式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: #pragma once与#ifndef
- 下一篇: KR C、ANSI C、C89、C90、