在 C 語言中,當有符號整數與無符號整數進行運算時,會發生「整數提升」與「通常算術轉換」。許多初學者會誤以為編譯器會先將字面常數 -1 轉換為無符號數 4294967295(假設 32 位元),再與無符號變數 i 相乘。實際上情況更微妙,理解這一點對避免溢位 Bug 至關重要。
#include <stdio.h>
int main() {
unsigned int i = 3;
printf("%u\n", i * -1); // 輸出 4294967293
return 0;
}
關鍵在於運算子優先級與類型轉換規則:
-1 是 int 型別的負數常數(補碼表示為 0xFFFFFFFF)。unsigned int 與 int 運算時,int 會被轉換為 unsigned int。此時 -1 變成 4294967295U。unsigned int 域內進行:3 * 4294967295U = 12884901885。0 ~ 4294967295),發生模 2^32 截斷,保留低 32 位:12884901885 % 4294967296 = 4294967293(即 0xFFFFFFFD)。所以「不是先轉再乘」,而是「轉換發生在運算子評估之前,運算本身在無符號域內完成,最後截斷」。
(int)i * -1。-Wsign-conversion),可在編譯期捕捉隱式轉換風險。輸出 4294967293 是無符號整數模運算的必然結果。掌握整數提升與轉換規則,才能寫出可攜帶、無 Bug 的 C 程式碼。