首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言隱式截斷陷阱:char 僅 8 位,289 變 33 的真相

     編輯:程式設計綜合問答

程式碼:

int i = 289;
char c = i; // 編譯警告:隱式轉換可能遺失資料
printf("%d", c); // 輸出 33,而非 289

為什麼 289 變成 33?這不是 Bug,是整型提升與截斷規則的必然結果。

二進制還原現場

289 (十進制)
= 1 0010 0001 (二進制,9 位)
= 0000 0001 0010 0001 (16 位 int 表示)

char 只有 8 位 → 截取低 8 位
低 8 位 = 0010 0001 = 0x21 = 33 (十進制)

標準規則:整數轉較窄類型 = 截取低位

  • 有號/無號皆同:直接捨棄高位位元
  • 無四捨五入、無飽和運算:純位元截斷
  • 結果視目標類型有號性解讀:char 有號性實作定義(通常有號),unsigned char 則為 0~255

驗證實驗

#include <stdio.h>
#include <limits.h>

int main() {
    int i = 289;
    signed char sc = i;   // 實作定義,通常 -128~127
    unsigned char uc = i; // 0~255
    printf("i=%d, sc=%d, uc=%u\n", i, sc, uc);
    // 輸出:i=289, sc=33, uc=33
    return 0;
}

常見危險場景

最佳實務

  1. 開啟編譯器警告:-Wconversion (GCC/Clang) 或 /W4 (MSVC) 會報 conversion from 'int' to 'char' may lose data。
  2. 使用 <stdint.h> 固定寬度類型:int8_t, uint16_t, int32_t,讓意圖顯性化。
  3. 必要時顯式截斷並註釋:uint8_t byte = (uint8_t)(value & 0xFF); // 取低 8 位。
  4. 單元測試邊界值:0, 127, 128, 255, 256, -1, -128。

結語

char c = 289; // c == 33 不是編譯器錯,是 C 語言「位元級截斷」語義的忠實執行。理解二進制表示、位寬限制與隱式轉換規則,是寫出健壯系統級程式碼的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
場景風險防範
網路協議解析 uint16_t → uint8_t高位截斷導致協議解析錯誤顯式 & 0xFF 或驗證範圍
檔案格式讀取 int → char負數變正數、大數變小數用 uint8_t、int32_t 明確寬度類型
遞迴/迴圈計數器 int → char超過 127 產生負數導致無限迴圈計數器用 int 或 size_t