資料表示法與數字系統

整數溢位(integer overflow)

整數溢位發生在一個計算產生的結果,大到塞不進為它預留的固定位元數,於是答案就錯了。想像一台有五個轉盤的舊里程表:一旦到達 99999 英里,再多一英里就翻回 00000。真實里程更高,但顯示器沒地方放多出來的位數,於是悄悄繞回。電腦整數行為相同——它們寬度固定,沒有成長的空間。

對無號 8 位元值,範圍是 0 到 255,所以 255 + 1 繞回 0;本該落在第九位的進位被直接丟棄。對有號二補數,這驚奇更銳利:範圍是 -128 到 +127,所以 127 + 1 繞回 -128——正加正竟可以得出負。硬體會偵測這種情況(當進入最高位的進位與從它出來的進位不同時,就發生有號溢位)並通常設定一個溢位旗標,但有沒有人檢查那個旗標則取決於程式。在許多語言裡,預設情況下那個錯誤的繞回值就照常往下流,彷彿什麼都沒發生。

這不是紙上談兵。溢位造成過真實災難:亞利安 5 號火箭在 1996 年部分因為一個值被擠進太少位元而溢位,最終被炸毀;而所謂的「2038 年問題」源自一個有號 32 位元時間戳,將在 2038 年一月溢位。誠實而重要的一點是:溢位通常是無聲的——不當機、不警告,只是一個悄悄錯掉的數——這正是它危險之處。在某些語言裡,有號溢位甚至在形式上是未定義行為,意味著編譯器可以假設它永不發生,並以令人意外的方式最佳化。

在有號 8 位元算術裡,127 + 1 = -128:0111 1111 + 0000 0001 = 1000 0000,而 1000 0000 在二補數裡是 -128。正加正卻翻成負——那個符號翻轉正是溢位發生的訊號。

有號溢位把 127 繞成 -128;結果塞得進位元,但數學上是錯的。

溢位通常無聲——沒有錯誤,只有一個悄悄錯掉的值——而在某些語言裡,有號溢位是編譯器可加以利用的未定義行為。真實故障(亞利安 5、2038 年問題)都可追溯到它。

又称
arithmetic overflowwraparound溢出繞回