Joel Spolsky 認為指針理解是天賦,但通過系統分析仍可掌握核心。指針是復合類型,包含兩層含義:
| 聲明 | 指針本身類型 | 去掉 * 後(指向對象類型) | 語義 |
|---|---|---|---|
int *p; | int * | int | 指向整數的指針 |
int **p; | int ** | int * | 指向「指向整數的指針」的指針 |
int (*parValue)[3]; | int (*)[3] | int [3] | 指向「含 3 個整數的數組」的指針 |
int (*pFun)(); | int (*)() | int () | 指向「無參返回 int 的函數」的指針 |
sizeof(指針) 永遠等於機器字長
void *p = malloc(100);
sizeof(p); // 4 (32位) / 8 (64位) —— 與分配的 100 字節無關
char str[] = "Hello";
char *p = str;
sizeof(p); // 同樣是 4/8
void Func(char str[100]) {
sizeof(str); // 此處 str 退化為指針,結果仍為 4/8
}
結論:sizeof(指針變量) 只反映指針自身大小,無法獲取動態分配內存塊大小。
& 與 *:互逆操作&x:取變量 x 的地址 → 得到指針(指針本身)*p:取指針 p 指向地址上的內容 → 得到指向對象適用對象:變量、數組、函數、類成員等。
malloc/new 運行時決定大小0L?
#define NULL 0
#define NULL (char *)0
#define NULL (void *)0
#define NULL 0L // 推薦
0L(long 型 0)是「值為 0 的整數常量表達式」,最符合標準定義,跨平台最安全
void Test() {
char *str = malloc(100);
strcpy(str, "hello");
free(str);
if (str != NULL) { // ❌ str 成野指針,非 NULL 但不可用
strcpy(str, "world"); // 破壞堆元數據,後果不可控
}
}
free(str);
str = NULL; // ✅ 防止野指針誤用
指針是「地址」與「類型」的復合體。掌握 指針本身值(地址) 與 指向對象(類型語義) 的二元性質,配合 &/* 互逆操作、sizeof 特性、空指針規範與三大編程鐵律,即可構建健壯、高效的 C/C++ 系統代碼。