天天看點

int、short、char 類型超出範圍指派__說說原碼,反碼,補碼

以下使用g++編譯器,win32平台)。

假設short類型的大小是2位元組,int類型的大小是4個位元組。short能表示-32768~32767之間的整數。

以下代碼:

short s=100000;

能通過編譯,s中的值是多少呢?

實際上,上面的代碼等價于short s=(short)100000,

也就是說,編譯器對100000強制轉化為short類型,一般是截取最後16位的值(假設編譯器将100000當int類型看待)。

現在要手算,s的值到底是多少呢?

第一步,100000%65536=34464,34464就是100000最後16位的值。

34464大于32767。如果用無符号的short類型存儲34464,那是足夠的(unsigned short的範圍是0~65536)。

但是,同樣的16位的值,用有符号的short類型儲存,就超出範圍了,它表示的就是另外一個值,是一個負數。

第二步,這個負數是多少呢?先看看有關原碼、反碼、補碼的内容。

這裡需要舉一個例子。負數在計算機中使用補碼表示的。

拿一個位元組的char類型來說,-1,原碼是1000,0001,

反碼是1111,1110(第一位是符号位,不取反,其他7為都取反),反碼加1就是補碼了。是以,-1的補碼是1111,1111。

這8位二進制,剛好等于unsigned char  a=2^8-1(2^8表示2的8次方)的8位二進制(1,0000,0000-0000,0001=1111,1111)。

這會不會是個巧合呢?再來看-2,原碼是1000,0010,反碼是1111,1101,補碼是1111,1110。

這8位二進制,剛好等于unsigned char b=2^8-2的二進制表示(1,0000,0000-0000,0010=1111,1110)。

再看-127,原碼是1111,1111,反碼是1000,0000,補碼就是1000,0001。

也就是說,-127在計算機中用1000,0001這八位二進制儲存。

這等價于unsigned char c=2^8-127的二進制表示,(1,0000,0000-0111,1111=1000,0001)。

特殊的,-128的原碼是什麼?它沒有原碼,因為7位二進制隻能表示到127, 對128沒法表示。

實際上,在計算機中,-128是用1000,0000表示的。這是補碼表示形式,不是負零。

為什麼呢?因為,1000,0000=2^8-128=1,0000,0000-1000,0000=1000,0000。這符合上面的規律。

那麼,計算機為什麼采用補碼來表示負數呢?是因為補碼可以友善計算,把減法變成加法。

比如,1-2=1+(-2)=0000,0001+1111,1110=1111111=-1。結果也是補碼的形式,很友善。

再比如,-1-2=(-1)+(-2)=1111,1111+1111,1110=1111,1101。

細心的讀者會發現,1111,1111+1111,1110産生了溢出。補碼的好處在于,可以不考慮溢出,結果照樣正确。

為什麼呢?-1-2=(2^8-1)+(2^8-2)=2^8-3+2^8,而2^8-3恰恰是-3的記憶體表示,另外的那個2^8就是進位了。

從這裡可以看出,把這個進位扔掉,結果剛好正确。

第三步,回到原來的問題,34464所表示的16為二進制,儲存在一個short類型中,結果是多少?

假設這個結果是-a,注意a是一個正數。

那麼,2^16-a=34464(仔細回顧第二步的内容)。

是以,-a=34464-2^16=-31072。

繼續閱讀