指針是 C 語言最強大也最易混淆的特性。本文針對四組高頻易混概念進行定義、語法、用法與陷阱的系統梳理。
| 概念 | 語法 | 含義 | 典型用途 |
|---|---|---|---|
| 常量指針 (Pointer to Constant) |
const int *p;int const *p; |
指向 常量 的指針。 不能通過 *p 修改所指內容,但 p 本身可指向其他地址。 |
函數參數傳遞只讀緩衝區:void print(const char *str); |
| 指針常量 (Constant Pointer) |
int *const p = &var; |
指針 本身是常量。 初始化後不可改變指向地址,但可通過 *p 修改所指內容。 |
固定映射的硬體寄存器地址:volatile uint32_t *const REG = (void*)0x4000; |
| 指向常量的指針常量 | const int *const p = &val; |
指針與所指內容均不可修改。 | 只讀配置表基址。 |
口訣:從右向左讀,* 左邊有 const → 所指內容不可變;* 右邊有 const → 指針本身不可變。
| 概念 | 語法 | 本質 | 示例 |
|---|---|---|---|
| 指針數組 | int *arr[10]; |
數組,元素類型為 int*。佔用 10 × sizeof(int*) 字節。 |
字符串數組:char *argv[] |
| 數組指針 | int (*p)[10]; |
指針,指向「含 10 個 int 的數組」。 佔用 sizeof(int*) 字節,步長為 10×sizeof(int)。 |
二維數組行指針:int (*p)[COLS] = matrix; |
區別關鍵:[] 優先級高於 *,故 int *p[10] 先結合 p[10];加括號 int (*p)[10] 則先結合 *p。
| 概念 | 語法 | 本質 | 應用場景 |
|---|---|---|---|
| 指針函數 | int* func(int a); |
函數,返回值類型為 int*。 |
返回動態分配的緩衝區指針、單例模式獲取實例指針。 |
| 函數指針 | int (*pf)(int a); |
指針,指向「接受 int、返回 int 的函數」。 | 回調函數、狀態機跳轉表、qsort 比較器、多態分發。 |
函數指針聲明讀法:pf 是一個指針 *pf,指向參數為 int、返回 int 的函數。
// 典型回調模式
typedef int (*cmp_fn)(const void*, const void*);
void sort(void *base, size_t n, size_t sz, cmp_fn cmp);
定義:未初始化、已釋放、超出作用域的指針。其指向地址不可預期,解引用導致未定義行為(數據破壞、程序崩潰、安全漏洞)。
int *p; *p = 10;free(p); *p = 20;int* foo() { int x; return &x; }int *p = NULL; 或 int *p = &var;free(p); p = NULL;搞清「誰修飾誰」是理解指針聲明的核心。養成良好的初始化、置空習慣,配合編譯器警告(-Wall -Wextra -Werror)與靜態分析,能消除 90% 以上的指針相關 Bug。