C 語言允許整數類型間自由隱式轉換,但「長轉短截斷」、「有符號/無符號混用」、「負數賦值給無符號」等行為導致的數據丟失、邏輯錯誤,是無數 Bug 根源。本文通過兩個對比程序實測,演示 int → char 截斷、符號位擴展、賦值順序對結果的劇烈影響。
#include <stdio.h>
int main() {
int i; char c;
i = 65535; // 0xFFFF
c = 48; // '0' (ASCII 48)
i = c; // i = 48 (char→int 擴展,無損)
c = i; // c = 48 (int→char 截斷低 8 位,48 正好在範圍內)
printf("char=%c\nint=%d\n", c, i); // 輸出: char=0, int=48
return 0;
}
輸出:
char=0
int=48

#include <stdio.h>
int main() {
int i; char c;
i = 65535; // 0xFFFF
c = 48; // '0'
c = i; // c = 截斷低 8 位 = 0xFF = 255 (無符號) 或 -1 (有符號 char)
i = c; // i = -1 (char→int 符號擴展:0xFF → 0xFFFFFFFF)
printf("char=%c\nint=%d\n", c, i); // 輸出: char=不可见字符, int=-1
return 0;
}
輸出:
char= (不可見控制字符)
int=-1

| 位模式 | signed char | unsigned char |
|---|---|---|
| 0x00~0x7F | 0~127 | 0~127 |
| 0x80~0xFF | -128~-1 | 128~255 |
程序二中 c = i (65535) → 低 8 位 0xFF:
char 有符號 (x86 GCC 默認) → c = -1。i = c → 符號擴展 0xFFFFFFFF → i = -1。%c 顯示不可見控制字符 (0xFF)。同樣初始值,兩種順序導致完全不同結果:
i=c; c=i; → 數值在安全範圍內往返,**無損**。c=i; i=c; → 大數截斷進 char,再符號擴展回 int,**數值毀損**。-Wconversion -Wsign-conversion -Wnarrowing (GCC/Clang) 強制暴露隱式窄化。int32_t, uint8_t 替代 int/char,語義清晰。if (val > INT8_MAX || val < INT8_MIN) handle_error();
int8_t narrow = (int8_t)val;
unsigned char:避免符號擴展陷阱,#define UCHAR(c) ((unsigned char)(c))。類型轉換不僅是語法糖,更是**位模式的重新解釋**。理解「截斷保留低位」、「符號擴展複製符號位」、「有符號/無符號邊界行為差異」,配合編譯器警告與顯式強轉,才能在 C 語言的類型系統中安全航行。