看似簡單的表達式往往隱藏著與直覺不符的行為。本文總結四類經典陷阱,給出正確寫法與底層原理解析。
n % 2 == 1 是錯的問題:負數取模在 C/C++ 中結果為負(-3 % 2 == -1),導致負奇數判斷失敗。
正確寫法:
// 方法 1:不等於 0
if (n % 2 != 0) // 正負奇數均為真
// 方法 2:位運算(最高效)
if (n & 1) // 末位為 1 即奇數,無分支預測失誤
原理:二進制最低位決定奇偶,& 1 直接提取該位,編譯器通常優化為單指令。
2.0 - 1.1 != 0.9現象:
printf("%.20f\n", 2.0 - 1.1); // 0.89999999999999991118
原因:十進制 0.1、1.1 等無法用二進制浮點數精確表示(類似 1/3 無法精確用十進制表示)。
解決方案:
printf("%.2f", 2.0-1.1) → 0.90(僅顯示層面);int cents = 200 - 110;boost::multiprecision::cpp_dec_float、Java BigDecimal("2.00").subtract(BigDecimal("1.10"))(**必須用字符串構造**,避免雙精度污染)。24 * 60 * 60 * 1000 * 1000代碼:
long weimiao = 24 * 60 * 60 * 1000 * 1000; // 微秒數
long haomiao = 24 * 60 * 60 * 1000; // 毫秒數
printf("%ld\n", weimiao / haomiao); // 輸出 5 (預期 1000)
原因:字面量默認 int,**運算過程中**溢出(32位 int 上限 ~21億,實際需 864億),結果截斷後再賦給 long。
修正:至少一個字面量加 L 強制長整型運算:
long weimiao = 24L * 60 * 60 * 1000 * 1000; // 正確輸出 1000
口訣:大數字面量運算,**首個常量加 L/LL**。
現象:
printf("%lx\n", 0x100000000L + 0xcafebabe); // 輸出 cafebabe (預期 1cafebabe)
原因:
0xcafebabe 無後綴 → int(最高位 1 → 負數);long + int → int 先**符號擴展**為 32 位 0xffffffffcafebabe;cafebabe,高位丟失。修正:第二個常量也加 L:
printf("%lx\n", 0x100000000L + 0xcafebabeL); // 正確輸出 1cafebabe
n & 1;L;這些陷阱雖小,卻能導致極難復現的 Bug。養成「看常量類型、想位模式、查標準行為」的習慣,是資深工程師的基本功。