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

C 語言類型轉換陷阱:有號/無號混合與整數提升實例解析

     編輯:關於C語言

前言

C 語言隱式類型轉換規則複雜,特別是有號/無號混合運算與整數提升,極易導致非直觀結果。本文取材自《深入理解計算機系統》,透過兩個經典案例深入剖析。

案例一:short 轉 unsigned 的兩階段過程

short sx = -12345;
unsigned uy = sx;
printf("uy = %u\n", uy); /* 輸出 4294954951 (0xFFFFCFC7) */

規則:轉換時先擴展位寬再改變符號性。即 `(unsigned)sx` 等價於 `(unsigned)(int)sx`,而非 `(unsigned)(unsigned short)sx`。
`-12345` (0xCFC7) → `int` 擴展為 0xFFFFCFC7 → `unsigned` 解讀為 4294954951。
若先轉 `unsigned short` 則為 53191 (0xCFC7),結果不同。C 標準強制要求前者。

案例二:有號/無號比較陷阱

-1 < 0U  /* 結果為 0 (假) */

原因:`0U` 為 `unsigned int`,`-1` 隱式轉為 `unsigned int` (4294967295U),比較變為 `4294967295U < 0U` → 假。

案例三:迴圈邊界隱藏錯誤

double sum_elements(double a[], unsigned length) {
    int i;
    double result = 0;
    for (i = 0; i <= length - 1; ++i)  /* length=0 時災難 */
        result += a[i];
    return result;
}

分析:`length` 為 `unsigned`,`length - 1` 亦為 `unsigned`。當 `length = 0`,`0 - 1` 下溢為 `UINT_MAX` (4294967295)。
`i` (signed) 與 `UINT_MAX` 比較,`i` 隱式轉 `unsigned`,條件 `i <= UINT_MAX` 恆真 → 迴圈無限執行 → 陣列越界崩潰。

修正:改用 `i < length` 或將 `length` 宣告為 `size_t` 並配合 `i < length`,避免減 1 操作。

總結:隱式轉換核心規則

  1. 整數提升:`char`/`short` 運算前提升為 `int` (或 `unsigned int`)。
  2. 算術轉換:運算元類型不同時,向「較高」類型轉換(無號優於有號、長優於短)。
  3. 有號/無號混合:有號隱式轉無號,按無號邏輯運算/比較。
  4. 賦值轉換:右值轉為左值類型,可能截斷或改變符號解讀。

防禦性寫法:避免有號/無號混合、邊界條件用 `< length` 而非 `<= length-1`、關鍵處顯式轉型。

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