C語言中的整數溢位
對於初學者來說,C語言的整數溢位可能一開始可能會不好理解。對於一個位元組的 unsignde char型別和signed char 型別。賦值一個超出其儲存範圍的數值時,
其真實儲存的數值並不等於我們賦值的資料。要弄清整數溢位問題,首先必須清晰計算機中數值都是以補碼形式儲存的,要會原碼、反碼和補碼的轉換。
下面分有符整數溢位和無符整數溢位分析。
一、有符整型溢位
比如下面這個程式,輸出不是129而是-127。
我們知道對於有符整型(signed char)它的儲存範圍為[-128,127],129已經超出向上溢位了。129的機器碼為【1000 0001】,計算機會取這八位作為補碼儲存。
補碼【1000 0001】是個負數,求其原碼減少1再對數值位取反可得到其原碼為【1111 1111】,這個值就是-127(最高位為符號位1,代表負數)。也可以把[-128,127]
看作汽車裡程表,當向上超出時就重新從起點開始。129-127 = 2,從新從-128開始這個值就是-(128-2+1) = -127。
再舉一個列子,下面這個程式輸出的結果為-112而不是400,同樣的分析可得出結果。
400的機器碼為【0000 0001 1001 0000】(2^8+2^7+2^4),計算機會取出低八位【1001 0000】作為補碼進行儲存,作為補碼這明顯是個負數,我們減1再對數值位取反可以得到其原碼
為【1111 0000】,這個數是-112(2^6+2^5+2^4)。用迴圈思想也可以驗證, 400超出上限400-127 -256 = 17,所以為-【128-17+1】 = -112。一般我們在將int型資料賦給char型變數的時候
編譯器也會發出警告如下:warning: overflow in conversion from 'int' to 'signed char' changes value from '400' to '-112' [-Woverflow]|。
二、無符整型溢位
無符整型溢位就簡單多了,因為正數的補碼和原碼一致。道理也是一樣的,這裡舉一個簡單例子分析一下。下面的程式輸出結果不是288,而是32。
我們知道unsigned char一個位元組儲存值的範圍是[0,255],288明顯已經向上溢位了。288的機器碼為【0000 0001 0010 0000】(2^8+2^5),計算機取出低八位【0010 0000】作為補碼
,正數補碼就是原碼,這個數就是32,迴圈思想也可驗證。同樣的編譯器也會發出相關警告:warning: unsigned conversion from 'int' to 'unsigned char' changes value from '288' to '32' [-Woverflow]|
整型溢位問題,只要對於計算機數值儲存形式(補碼)和補碼原碼轉換有了解就不難理解了。