看似簡單的unsigned int + int運算,隱藏著許多資深工程師也會踩的坑。通過兩道題目揭示整數提升與無符號轉換規則。
unsigned int a = 6;
int b = -20;
printf("%d\n", a + b); // 輸出?
(a + b) > 6 ? puts(">6") : puts("<=6"); // 判斷?
答案:>6
unsigned int a = 6;
int b = -2;
printf("%d\n", a + b); // 輸出?
(a + b) > 6 ? puts(">6") : puts("<=6"); // 判斷?
答案:<=6
unsigned int等級 ≥ int,運算時int隱式轉換為unsigned intunsigned int,溢出按模2ⁿ環繞-20的32位補碼:0xFFFFFFEC(4294967276)unsigned int:42949672766 + 4294967276 = 4294967282(0xFFFFFFF2)printf("%d")按有符號解釋:-14(a+b) > 6:左邊無符號4294967282,右邊6提升為無符號 → true-2的補碼:0xFFFFFFFE(4294967294)6 + 4294967294 = 4294967300 → 溢出環繞 → 4(0x00000004)printf("%d")輸出:44 > 6 → false最高位溢出位被丟棄是題目二結果為4而非巨大數值的原因。無符號加法模2³²運算,進位位直接丟失:
0000...0110 (6) + 1111...1110 (-2 as unsigned 4294967294) = 10000...0100 → 截取低32位 → 0000...0100 (4)
(long)a + b-Wsign-compare、-Wsign-conversion務必開啟%d與%u只影響輸出格式,不改變內存位模式C99 §6.3.1.3/6.3.1.8:當有符號與無符號同寬度運算時,有符號轉無符號;轉換保持二進制位模式不變(即補碼直接重新解釋)。
這兩道題精準暴露了「直覺以為是6-20=-14,比較時按有符號邏輯」與「實際按無符號模運算」的認知鴻溝。計算機不講直覺,只講位模式。