C語言入門易錯點:整型提升和截斷
C語言入門易錯點:整形提升和截斷
什麼是整型提升
C的整形算術運算總是至少以預設整形型別的精度來進行的。為了獲得這個精度,表示式中的字元和短整型運算元再使用之前被轉轉為普通整型,這種轉換稱為整型提升。
整型提升的意義
表示式的整型運算要在CPU的相應運算器件內執行,CPU內整型運算器(ALU)的運算元的位元組長度一般就是int
的位元組長度,同時也是CPU的通用暫存器的長度。
因此,即使兩個char型別的相加,在CPU執行時實際上也要先轉換為CPU內整型運算元的標準長度。
int
長度的整型值,都必須先轉換為int
或unsigned int
,然後才能送入CPU去執行運算。
在什麼情況下會發生?
我們在進行邏輯運算的時候,可能一個簡單的比較或者輸出就會出現這種情況。
char num = 1;
printf("%d\n", num);
printf("%u\n", num);
執行效果為:
- 第一次提升:
我們此處將num
以無符號整型的格式進行列印,此時會輸出4294967295
為什莫是最大的數呢?
因為
num
的型別為char
只佔用1個位元組,因為要將其以整型的格式打印出來,這時候就出現了第一次整型提升,將原本為char
型別的資料轉換為了int
,將其提升為整型。
我們看到將其按照整型打印出來的結果為 -1
。
- 第二次提升:
我們將其再次進行列印,不過以無符號整型的方式進行列印,但此時他輸出的是一個無符號整型能儲存的最大值。這時候出現了第二次整型提升,將
char
提升為unsigned int
無符號整型。為什莫輸出的是最大值呢?
計算機在儲存資料的時候都是以0 1 程式碼儲存在計算機內,正數和負數都存的是他的補碼。正數的反碼和補碼都等於他的二進位制數,負數的補碼等於他的反碼 + 1。
這時候再來看,我們是將 -1 以無符號整型的形式列印,其對應的補碼為 11111111 11111111 11111111 11111111
,當提升以後會將其看為無符號,於是就將其輸出,也就是我們看到的最大值
截斷
我們先來看看這段程式碼
char i=129;
printf("%d\n",i);
我們不妨猜一猜,輸出的結果會是多少?經過上面的講解,在這裡,會出現整型提升,很明顯。但是輸出的結果卻和我們預料的大相徑庭。
為什麼會出現這種結果,通過整型提升不是應該輸出一個129嗎?這裡我們再來了解一下,截斷。
出現整型提升時,只會將該型別的資料讀取方式改變,但是並不會改變他的儲存大小。char只有一個位元組,將一個4位元組的整數強行賦值給他,此時,他就會將溢位的位自動捨棄,只會保留他能儲存的最大位,也就是8個位元位,也就是說,經過提升和截斷以後,他的二進位制數為1111 1111
將其按照整型列印時,其只能讀出8個位元位,而且8個位都是1,第一位作為符號位,即只有後7位儲存資料,固打印出來的數為: -127