資料表示法:位元、位元組與數值

整數提升與轉換

當你在 C 裡寫「a + b」時,你或許以為這兩個值就照原樣相加。但在加法發生之前,編譯器可能悄悄改變它們的型別,把窄的值加寬,並調和有號與無號。這些自動、幕後的型別變更就是整數提升與轉換,而因為它們在原始碼裡看不見,便成了「為什麼答案錯了?」這類意外的豐富來源。

整數提升是第一條規則:任何比 int 窄的型別的值(char、short、位元欄位)在算術前都會提升為 int。所以把兩個各為 200 的 unsigned char 相加,並不會在 255 處環繞——兩者都提升為 int,結果是 400,一個普通的 int。接著是「慣常算術轉換」,把二元運算子的兩個運算元對齊到一個共同型別:大致上,較窄的加寬成較寬的,而——危險的部分來了——如果一個運算元是無號、另一個是同寬的有號,則「有號」的那個會被轉成無號。比較「-1 < 1u」最後是「假」就是這麼來的:那個 -1 變成了一個極大的無號值。

轉換也發生在賦值和傳遞引數時:把一個寬的值存進較窄的型別會截斷它(只留低位),而在有號與無號之間轉換則重新解讀位元模式。這一切都不是隨機的——規則精確,值得學習——但很容易被坑。實務上的防禦是:在一個運算式內保持型別一致、避免混用有號與無號、當你真的有意時用型別轉換把轉換寫明確,並開啟像 -Wconversion 和 -Wsign-conversion 的警告,讓編譯器在那些無聲的變更咬人之前先指出它們。

unsigned char a = 200, b = 200; int s = a + b; 得到 s == 400,因為兩者在相加前都提升為 int。但 if (-1 < 1u) 是「假」:在比較中 -1 轉成了 UINT_MAX。

窄型別提升為 int;有號/無號混用會轉換有號的那個。

提升為 int 意味著窄的無號型別在算術中「不會」像你以為的那樣環繞——它們先以 int 計算;反過來,混用有號與無號可能悄悄把一個負值變成一個極大的正值。

又稱
implicit conversiontype coercionusual arithmetic conversions整數提升