案例 1:16 位有符號整數溢出演示
main() {
int a, b;
a = 32767; // INT16_MAX
b = a + 1; // 溢出:32767 + 1 = -32768 (補碼環繞)
printf("\na=%d, a+1=%d\n", a, b);
a = -32768; // INT16_MIN
b = a - 1; // 溢出:-32768 - 1 = 32767
printf("\na=%d, a-1=%d\n", a, b);
getch();
}
逐行註解
| 代碼 | 註解 | 補充說明 |
int a,b; | 定義兩個有符號整型變量 (16 位環境下範圍 -32768~32767) | 現代 32 位環境 int 通常 32 位,需用 int16_t 復現 |
a=32767; | 賦最大值 | |
b=a+1; | 溢出:二進制 0x7FFF + 1 = 0x8000,補碼解讀為 -32768 | 有符號溢出屬 UB,但二補碼機器普遍環繞 |
printf(...) | 輸出 a=32767, a+1=-32768 | |
a=-32768; | 賦最小值 | |
b=a-1; | 溢出:0x8000 - 1 = 0x7FFF → 32767 | |
printd | **拼寫錯誤** 應為 printf | 編譯報錯:隱式聲明/未定義標識符 |
getch() | 非標準函數 (conio.h),等待按鍵 | 跨平台用 getchar() |
案例 2:字符大小寫轉換與 ASCII 碼操作
main() {
char c1, c2, c3;
c1 = 'a'; // ASCII 97
c2 = 'b'; // ASCII 98
c1 = c1 - 32; // 97-32=65 → 'A'
c2 = c2 - 32; // 98-32=66 → 'B'
c3 = 130; // 超出 signed char 範圍 (-128~127),溢出實現定義
printf("\n%c %c %c\n", c1, c2, c3); // 輸出 A B (第3個字符取決於編碼頁)
printf("%d %d %d\n", c1, c2, c3); // 輸出 65 66 -126 (若 char 有符號)
getch();
}
逐行註解
| 代碼 | 註解 | 關鍵知識點 |
char c1,c2,c3; | 定義三個字符類型變量 | char 是否有符號由實現定義 |
c1='a'; | 字符常量隱式轉換為 ASCII 碼值 | 'a'=97, 'A'=65, 差值 32 |
c1=c1-32; | 整數提升後相減,結果截斷存回 char | 小寫轉大寫:減 32 或 & 0xDF |
c3=130; | 130 > 127,有符號 char 溢出 → 實現定義 (通常補碼 -126) | 無符號 char 則為 130 |
printf("%c") | 按字符輸出 | 130 在擴展 ASCII 可能顯示 é/═ 等 |
printf("%d") | 按整數輸出 (整數提升為 int) | 有符號 char -126,無符號 130 |
教學價值總結
- 案例 1 直觀展示**有符號整數溢出環繞**,理解補碼表示、UB 風險、定寬類型必要性。
- 案例 2 揭示**字符本質是小整數**,大小寫轉換靠 ASCII 碼差值、
char 符號性陷阱、擴展字符集顯示不確定性。
- 代碼中存在拼寫錯誤 (
printd) 和非標準函數 (getch),適合作為「找錯誤」練習題。
註解不是翻譯代碼,而是**揭示背後機制、標準規定、工程陷阱**。