前言
學習C語言時,我對于C語言基本資料型別不太懂,后來學習計組之后,了解了計算機內部資料的存盤,這篇文章將從底層,剖析基本資料型別在計算機中是如何存盤,
整型資料的表示方法
在計算機中,資料以二進制的方式存盤,即我們平時所使用的十進制數,都會被轉化為0101等資料,如十進制的12,轉化成二進制就是1010,
我平時習慣將四個二進制數寫在一起,第一,便于書寫時一眼能看清位數;第二,也便于二進制與16進制的轉換,
比如十進制數99,我會先看成64+32+2+1,因此轉換成二進制數的時候,就是0110 0011,要記得常見的2的幾次方,比如2的0次方等于1, 2的十次方等于1024,
計算機的主存盤器是由一個個存盤0和1的存盤元件組成,每個存盤元里面存盤的一個二進制數,我們成為1bit ,我們常用的計算機中,一般是8個存盤元為一組,存盤的8個二進制數為1B(位元組),
參與運算的機器數有兩種,一種是無符號數,一種是有符號數,
無符號數中,整個機器字表示的二進制位均表示數值,比如計算機中存盤了機器數1000 0001,即表示十進制數129,當我們在C語言中某個資料型別前加入unsigned時,表示該數為無符號數,存盤的時候,首位就是數值位,比如 存盤129,且該計算機是8位計算機,那么在計算機中存盤的就是1000 0001,
對于有符號數,計算機中最高位,即最前面的那一位表示符號,0表示該數為正數,1表示該數為負數,
對于有符號數的表示,有四種方式,原碼、補碼、反碼、移碼,
我們先不必在意這四個碼分別是什么,
我們只需要知道,我們常用的計算機,一般都是以補碼存盤,
因此,我們先介紹原碼和補碼,為了便于舉例,我們假設某個計算機是8位計算機,
127轉換成二進制是多少呢——0111 1111,那-127呢?如果直接轉換,根據之前所講的首位為1則為負數,我們很容易得到1111 1111,
是的,這就是原碼,我們不必死扣概念,知道這個例子即可,也就是說,正數和負數之間的差別,其實僅僅是首位的符號位,
但是,在計算機中存盤的,并不是原碼,而是補碼,(為什么?感興趣的可以查一下相關的資料)
對于補碼而言,其正數與原碼的表示方式完全相同,也就是說,127,在計算機中存盤的,其實就是0111 1111,那-129呢?先給結論,-127是以1000 0001存盤的,
是不是沒有找出規律?
那請把目光回傳到我講補碼時的1111 1111,其實,負數的補碼就是將原碼的符號位不變,數值位全部取反,最后在末位+1,因此,我們就得到了-127的補碼——1000 0001,
發現了沒有,無符號數129和有符號數的-127的存盤,都是1000 0001,
理解了這兩種碼,那在C語言中,int,short int,long,long long僅僅是位數上的差別,
需要注意的是,32位機器中, int 是4位元組,short int 是2位元組,long 是4位元組,long long是8位元組,
執行以下代碼,我們可以得到結果,
int main()
{
printf("sizeof_int= %d \n", sizeof(int));
printf("sizeof_short= %d \n", sizeof(short));
printf("sizeof_long= %d \n", sizeof(long));
printf("sizeof_long long= %d \n", sizeof(long long));
}

浮點型資料的存盤
對于浮點數的存盤,目前遵循一個標準——IEEE 754標準,
該標準中,將資料分為以下幾部分,
數符、階碼部分、尾數部分,
我們先舉一個十進制的例子,1001用科學計數法怎么表示?
——1.001×10^4,
這里的4指的就是階碼,因為是十進制,因此10為底,而1.001,就是尾數,
比如9,轉化成二進制就是1001,那用科學計數法表示,就是1.001×2^0011,0011就是十進制的3,此時要寫成二進制,
以float為例,數符即表示該數的符號,存盤在最高位,占1bit,階碼是中間的8位,尾數則是后面的23位,這是規定,知道即可,
因此,float在32位機器中,占32bit,即4B,
注意,表面上是23位,實際上這23位都是小數點后的23位,小數點前面的1被隱含了,
比如上面的9的尾數,1.001,在存盤的時候只存盤001,前面的1被隱含了,
在我們上面舉的例子中,尾數部分決定了一個數的精確度,也就是說,float尾數實際精確度為24位,
為什么要強調這一點?
比如我們要將int轉換成float,那有沒有可能出現精度丟失?答案是肯定的,int可以保留32位精度,而float只能保存24位,因此是可能出現精度丟失的,
我們給出如下代碼
int main()
{
printf("sizeof_float= %d \n", sizeof(float));
printf("sizeof_double= %d \n", sizeof(double));
}

可以看出,double需要用8B存盤,根據IEEE 754標準,double保存精度的位數為52+1位(+1同float),即將int轉化為double時,不會出現精度丟失,
注意:float和double在存盤一些小數時,無法實作精確存盤,比如,小數點后,可以精確的是0.5, 0.25,0.125,0.75等,而對于2.323,1.332這類數,計算機是無法精確存盤的,因此,在判斷陳述句中,我們不能判斷兩個小數資料是否相等,
如下列代碼是不規范的,
double a ,b;
...
if (a == b)
字符型的存盤
int main()
{
printf("sizeof_char= %d \n", sizeof(char));
}

可以看出,char型在記憶體中占1B,
char型存盤的時候后并不是把該符號存盤到記憶體中,而是將某些資料以二進制的形式放到記憶體中,這些資料就是ASCII碼值,該表具體如下:

由圖可知,不同的ASCII碼對應不同的字符,
小結
C語言中,資料型別分為整型、實數型、字符型,整型又分為short, int ,long, long long, 實數型又分為float, double等,不同的型別其存盤所占的位元組數不同,
我們要謹慎使用強制型別轉換,要注意精度丟失的問題,編程時要非常小心,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/247753.html
標籤:其他
上一篇:讀書筆記-精準努力-自信與自卑
下一篇:進制
