本文整理 C 語言核心基礎知識點:有符號整數編碼、編譯鏈接流程、數據類型模型(ILP32/LP64)、常數後綴、常量存儲、scanf 掃描集與返回值、指針與下標效率差異、浮點格式 %f/%lf 差異,附 GDB 調試實證。
| 值 | 原碼 | 反碼 | 補碼 |
|---|---|---|---|
| +6 | 0000 0110 | 0000 0110 | 0000 0110 |
| -6 | 1000 0110 | 1111 1001 | 1111 1010 |
-[2^(n-1), 2^(n-1)-1],如 int8: -128~127-x = ~x + 1(按位取反加一)源碼 (.c) ↓ 預處理 (cpp) - 展開宏、頭文件、條件編譯、去除註釋 預處理輸出 (.i) ↓ 編譯 (cc1) - 詞法/語法分析、優化、生成汇編 汇編碼 (.s) ↓ 汇編 (as) - 汇編指令 → 機器碼目標文件 目標文件 (.o) ↓ 鏈接 (ld) - 符號解析、地址重定位、合併段、生成可執行文件 可執行文件
| 類型 | ILP32 (32位 Unix) | LP64 (64位 Unix/Linux) | LLP64 (Windows 64位) |
|---|---|---|---|
| char | 8 | 8 | 8 |
| short | 16 | 16 | 16 |
| int | 32 | 32 | 32 |
| long | 32 | 64 | 32 |
| long long | 64 | 64 | 64 |
| pointer | 32 | 64 | 64 |
| size_t | 32 | 64 | 64 |
| 後綴 | 類型(按優先級) | 示例 |
|---|---|---|
| 無 | int → long → long long | 100, 4000000000 |
| u/U | unsigned int → unsigned long → unsigned long long | 100u, 4000000000U |
| l/L | long → long long | 100L |
| ul/UL/lu/LU 等 | unsigned long → unsigned long long | 100UL |
無後綴十進制常數**首個能容納的有符號類型**;十六/八進制允許無符號類型。
| 常量 | 示例值 | 存儲大小 | 說明 |
|---|---|---|---|
| 整數字面量 | 1 | 2 字節 (unsigned short) | 編譯器根據值大小選類型 |
| 字符字面量 | '1' | 1 字節 (char) | ASCII 碼 0x31 |
| 字符串字面量 | "1" | 2 字節 | 含結束符 \0,類型 const char[2] |
%[...]char buf[100];
scanf("%[^\n]", buf); // 讀取整行(不含 \n)
scanf("%[a-z]", buf); // 僅讀小寫字母
// 方式 A:下標 for (i = 0; i < n; i++) a[i] = 4; // 方式 B:指針 for (p = a; p < a + n; p++) *p = 4;
本質:a[i] 等價 *(a + i),每次計算地址需加法;指針版僅需遞增。現代編譯器(-O2)會**自動將下標循環優化為指針形式**(強度削減),手寫優化多為冗餘。可讀性優先。
%f、%lf、%Lf 統一處理 double(float 會默認提升為 double)%f → float *(4 字節)%lf → double *(8 字節)%Lf → long double *double y;
scanf("%f", &y); // 錯誤:寫入 4 字節,高 4 字節殘留垃圾
// GDB 觀察:y = 4.85e-270(垃圾位模式被解釋為 double)
結論:scanf 讀 double **必須用 %lf**,讀 float 用 %f。printf 兩者通用。
C 語言基礎看似枯燥,實則是**理解計算機系統運行機制的鑰匙**。補碼統一加減法、編譯鏈接揭示符號解析、數據模型決定跨平台移植性、scanf 格式匹配關乎內存安全、浮點格式區別反映類型系統嚴謹性。建議:配合 GDB 觀察內存佈局、彙編輸出、棧幀變化,將抽象概念落地為可見現象。