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

從經典 Bug 深入解析 C 語言隱式類型轉換陷阱

     編輯:關於C

一個令人費解的 Bug

出自《C 專家編程》的經典範例:

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

int main(void) {
    int d = -1, x;
    if (d <= TOTAL_ELEMENTS - 2)
        x = array[d + 1];  // 這行永遠不會執行!
    return 0;
}

明明 d = -1,TOTAL_ELEMENTS = 7,-1 <= 5 應為真,為何進不去?

根本原因:signed/unsigned 比較規則

  • sizeof 回傳 size_t(無號整數)
  • TOTAL_ELEMENTS 為 unsigned int
  • d 為 signed int
  • 比較時 d 隱式轉為 unsigned int,-1 變成極大正數(0xFFFFFFFF)
  • 條件永遠為假

C 語言隱式類型轉換規則詳解

傳統 K&R C 規則

  1. char、short → int;float → double
  2. 運算元類型提升:double > long > unsigned > int

ANSI C 新標準(整型提升 + 尋常算術轉換)

  1. 整型提升:char、short、位段 → int 或 unsigned int(視範圍而定)
  2. 尋常算術轉換:低類型向高類型轉換
  3. 有號/無號混合:
    • unsigned long vs 其他 → 都轉 unsigned long
    • long vs unsigned int:若 long 能容納 unsigned int 則轉 long,否則轉 unsigned long
    • unsigned int vs int → 轉 unsigned int

實例分析

假設 int 16 位元,long 32 位元:

  • -1L < 1U:1U 轉 signed long,比較為真
  • -1L > 1UL:-1L 轉 unsigned long 變極大,比較為真

避坑指南

  1. 避免有號/無號直接比較
  2. 必要時強制轉型:(int)sizeof(...)
  3. 開啟編譯器警告(-Wsign-compare)
  4. 使用 static_assert 或概念檢查
「類型轉換帶來的 bug 往往難以直接調試出來,稍不注意可能對整個專案造成無法預測的後果。」
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved