首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C 語言經典陷阱:有號與無號比較導致的邏輯錯誤

     編輯:關於C

現象重現

看似合理的程式碼卻輸出 the bug is out!:

int array[] = {23, 34, 12, 17, 204, 99, 16};
#define TOTAL_ELEMENTS (sizeof(array)/sizeof(array[0]))

int main() {
    int d = -1;
    if (d <= (TOTAL_ELEMENTS - 2)) {
        printf("d <= TOTAL_ELEMENTS-2\n");
    } else {
        printf("the bug is out!\n");  // 實際執行這一行
    }
    return 0;
}

根本原因:整數提升與無號轉換

  1. sizeof 回傳 size_t(無號整數),故 TOTAL_ELEMENTS 為 unsigned int。
  2. TOTAL_ELEMENTS - 2 仍為無號型別。
  3. 比較運算子 <= 觸發 整數提升:有號 d 轉換為無號 unsigned int。
  4. -1 轉為無號後變成 UINT_MAX(4294967295),遠大於 5,條件判斷為假。

修正方案

// 方案一:強制轉型
if (d <= (int)(TOTAL_ELEMENTS - 2))

// 方案二:變數改為 size_t
size_t d = 0;  // 避免負值

// 方案三:分開判斷
if (d >= 0 && d <= (int)(TOTAL_ELEMENTS - 2))

防禦性編碼建議

  1. 少用無號型別:除非處理位元操作、二進制掩碼,否則優先用 int / long。
  2. 混合型別時顯式轉型:消除編譯器隱式轉換的驚喜。
  3. 開啟編譯器警告:-Wsign-compare (GCC/Clang) 可在編譯期捕捉此類問題。
  4. 靜態分析工具:Cppcheck、Clang Static Analyzer 可自動偵測有號/無號比較缺陷。

延伸閱讀

《C 專家編程》第 1 章詳細論述此陷阱;CERT C 編碼標準 INT02-C「理解整數轉換規則」提供規範化指導。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved