許多初學者感嘆「C語言太難」,實則是被語法細節淹沒,未掌握底層邏輯。C語言是系統編程的基石,設計哲學是「信任程序員、暴露硬件、零開銷抽象」。學好C,不僅是學語法,更是建立計算機系統思維:內存佈局、指針算術、調用約定、編譯鏈接、運行時環境。本文提煉四大核心支柱,助你構建知識骨架。
C的I/O核心是printf/scanf族函數,通過格式字符串解析參數,**編譯器不檢查格式與參數匹配**(現代編譯器有警告),運行時錯誤極其隱蔽。
scanf需地址,對嵌套結構需逐層取址。技巧:用臨時變量接收再賦值,避免直接&a[i][j]易出錯(尤其結構體數組)。%d/%i (有符號十進制)、%u (無符號)、%x/%X (十六進制)、%f/%e/%g (浮點)、%c (字符)、%s (字符串)、%p (指針)、%n (寫入已輸出字符數)。長度修飾符:hh(char), h(short), l(long/double), ll(long long), L(long double), z(size_t), t(ptrdiff_t)。**必須匹配實參類型**,否則UB。%[^\n] 讀整行,%*c 忽略字符,%*d 跳過整數。scanf返回成功匹配項數,必須檢查返回值處理輸入錯誤/EOF。stdin默認行緩衝,殘留換行符導致後續%c/%[^\n]讀空。習慣:while(getchar() != '\n'); 清行,或用fgets讀行再sscanf解析(更安全)。C有15級優先級,從高到低:後綴 `() [] -> .` → 單目 `++ -- + - ! ~ * & sizeof` → 乘除模 `* / %` → 加減 `+ -` → 移位 `<< >>` → 關系 `< <= > >=` → 相等 `== !=` → 按位與 `&` → 按位異或 `^` → 按位或 `|` → 邏輯與 `&&` → 邏輯或 `||` → 條件 `?:` → 賦值 `= += -= ...` → 逗號 `,`。同級按結合性:單目/賦值/條件 **右結合**,其餘 **左結合**。
i = i++ + ++i; (UB)、a[i] = i++; (C++17前UB)。**原則:同一標量對象在無序列點間不得多次修改,或修改後讀取用於確定新值以外目的**。a = b ? c : d 正確,a = b ? c : d = e 解析為 a = b ? c : (d = e)。指針本質:內存地址的類型化標籤。理解指針,必須理解內存模型:字節寻址、對齊、棧/堆/數據/代碼段、虛擬地址空間。
T *p; — p 指向類型 T 的對象。讀法:*p 是 T。p + n → 地址 + n * sizeof(T)。**只能在同一數組/對象內/尾後計算**,否則UB。T **p 指向 T*,用於修改指針本身、動態二維數組、命令行參數 char **argv。const T *p / T const *p (指向常量),T *const p (常量指針),const T *const p (雙重常量)。static_cast。Ret (*fp)(Arg1, Arg2);,回調、狀態機、插件架構核心。free後未置NULL、返回局部變量地址。鐵律:聲明即初始化,釋放即置NULL,不返回棧地址。strcpy/strcat/sprintf不檢查長度。**用 strncpy/strncat/snprintf 或 C++ string/span。**int *p = (int*)malloc(n); 後 p[i] = ... 違反嚴格別名規則 (strict aliasing) 可能導致優化錯誤。**用聯合體、memcpy、char* 字節訪問合規轉換。**C函數僅支持傳值調用。傳引用通過傳遞地址(指針)模擬。掌握函數,就是掌握調用約定:參數壓棧/寄存器傳遞、返回值傳遣、調用者/被調用者保存寄存器、棧幀佈局、setjmp/longjmp非局部跳轉。
<stdarg.h> va_list/va_start/va_arg/va_end,配合格式字符串實現printf類函數。**注意類型安全缺失,C++17 std::variant/折疊表達式更優。**inline 建議,__attribute__((noreturn))、pure、const、hot/cold 引導編譯器優化。C語言沒有「高級特性」堆砌,只有樸素而強大的原語。精通C,不是背誦語法,而是內化計算機系統模型。當你能在腦海中運行代碼、預見內存佈局、推演性能特徵、定位最棘手的UB——你就真正掌握了C。這條路很長,但每一步都通往計算機科學的核心。