經典著作《C和指針》被公認為進階 C 語言必讀。本文提煉書中最高頻、最易錯、最實戰的知識點,構建系統性速查筆記。
int ch;
while ((ch = getchar()) != EOF && ch != '\n'); // 清行緩衝
// 注意:ch 必須為 int,接收 EOF;括號保證賦值先於比較
gets() 禁用(無緩衝區溢出檢查),改用 fgets(buf, sizeof(buf), stdin)。
| 序列 | 字符 | 序列 | 字符 | 序列 | 字符 |
|---|---|---|---|---|---|
??( | [ | ??) | ] | ??! | | |
??< | { | ??> | } | ??= | # |
??/ | \ | ??' | ^ | ??- | ~ |
現代編譯器默認關閉,但維護舊代碼時可能遇見。
char 是否有符號由編譯器決定,不可假設。signed char 或 unsigned char。char,強制轉換可能產生警告,需權衡。int *a; // a 是指向 int 的指針
int *b, c, d; // 僅 b 是指針,c/d 是 int —— 易誤區!
int const *pci; // 指向 const int 的指針(底層 const)
int *const cpi; // const 指向 int 的指針(頂層 const)
int const *const cpci; // 雙重 const
口訣:* 靠近類型修飾被指物,靠近變量名修飾指針本身。
char msg[] = "Hello"; // 陣列初始化:拷貝字符到棧上,可修改
char *msg = "Hello"; // 指向唯讀字面量:嘗試修改導致 UB
上下文決定含義:初始化陣列時為初始化列表,其他場合為字面量指針。
r = s + (t = u - v) / 3;y + 3;(無副作用,編譯器優化掉),getchar();(有副作用:讀取並丟棄字符)。printf() 返回輸出字符數,通常被忽略,其輸出為副作用。/* falls through */。continue 僅作用於循環,不影響 switch;若 switch 在循環外,continue 無效。sizeof(a = b + 1) 不會賦值給 a。sizeof(arr) 返回整個陣列大小;&arr 類型為指向陣列的指針。++a:先增後用(值為增後值);a++:先用後增(值為增前值)。++a = 10; 錯誤:結果是右值,不可賦值。f() + g() + h() 三函數調用順序不定,若有副作用必須拆分語句。c + --c:未定義行為(修改與讀取無序列點)。p + n 等價 p + n * sizeof(*p)
p2 - p1 等價 (p2 - p1) / sizeof(*p1) // 結果為元素個數差
// 標準允許指向尾後元素的指針比較,禁止指向首前元素
int a[5]; int *p = a; 合法;a++ 非法;p++ 合法。int m[3][10]; → m 類型為 int (*)[10](指向 10-int 陣列的指針)。int (*f)(); // f 是函數指針,指向返回 int 的函數
int *(*f)(); // 指向返回 int* 的函數指針
int (*f[])(); // f 是陣列,元素為函數指針
int *(*f[])(); // 陣列元素為指向返回 int* 函數的指針
口訣:從變量名出發,按優先級 () [] > * > 型別,遇括號優先處理組內內容。
"xyz" + 1 // 指向 'y'
*"xyz" // 'x'
"xyz"[2] // 'z'
putchar("0123456789ABCDEF"[val % 16]); // 十六進制字符查表
if (strlen(x) >= strlen(y)) // 正確
if (strlen(x) - strlen(y) >= 0) // 永真!無符號減法回繞
| 函數 | 功能 |
|---|---|
strchr(s, c) | 查找 c 首次出現位置 |
strrchr(s, c) | 查找 c 最後出現位置 |
strpbrk(s, set) | 查找 set 中任意字符首次位置 |
strspn(s, set) | 前綴匹配 set 字符長度 |
strcspn(s, set) | 前綴不匹配 set 字符長度 |
strtok(s, sep) | 分割字符串(破壞原串、非線程安全) |
int 位段符號性實現定義。int 寬度(16/32 位差異)。嚴肅可移植代碼避免使用位段。
| 函數 | 特點 |
|---|---|
malloc(n) | 分配 n 位元組,不初始化,失敗返 NULL |
calloc(n, sz) | 分配 n*sz,歸零,適合陣列 |
realloc(p, n) | 調整大小,可能移動記憶體,舊指針失效 |
free(p) | 釋放,free(NULL) 安全無操作 |
對齊保證:malloc 返回地址滿足最嚴格類型對齊要求。
這 18 大知識點覆蓋了《C和指針》精髓的 80%,建議收藏反芻,實戰中遇到指針、字符串、記憶體疑難雜症時速查。