指針 = 記憶體地址。每個位元組擁有唯一編號(地址),透過地址可定位資料。指針變數則是「存放地址的變數」。
比喻:房間號「301」是地址(指針),房間內的人/物是資料。指針變數像是手上拿著「301」紙條的管家。
int a = 12; // 變數 a,佔 4 bytes,假設地址 0x1000
int *p = &a; // p 是指向 int 的指針變數,值為 0x1000
printf("%d\n", *p); // 解參考:透過地址 0x1000 讀取值 12
*p = 20; // 透過指針修改 a,a 變為 20
int *p:*p 是 int → p 是指向 int 的指針。&a:取址運算子,獲得變數地址。*p:解參考/間接訪問運算子,透過地址存取資料。int a = 12; int *p = &a; // 一級指針,存 a 的地址 int **pp = &p; // 二級指針,存 p 的地址 // 記憶體圖示: // pp (0x2000) -> p (0x1000) -> a (0x1000) = 12 **pp = 30; // 等價於 a = 30
用途:函式需修改呼叫端的指針變數(如 malloc 回傳指針、鏈表頭節點修改)。
| 誤區 | 正確觀念 |
|---|---|
| 指針就是地址,沒有類型 | 指針有類型(int*, char*),決定解參考讀取幾 bytes、指標運算步長 |
| *p++ 等於 *(p++) | 優先級相同,右結合,確實是 *(p++),但語意常混淆,建議加括號 |
| 指針變數未初始化即可用 | 野指針極危險,定義即初始化:int *p = NULL; 或 = &var; |
| const int *p 與 int *const p 相同 | 前者「指向常數的指針」(不可透過 p 改值),後者「常數指針」(p 本身不可改指向) |
int *arr[3]; // 指針陣列:3 個 int* 元素 int (*parr)[3]; // 陣列指針:指向「含 3 個 int 的陣列」的指針
閱讀技巧:從變數名往外,先看右邊 []/(),再看左邊 *。
指針是 C 語言靈魂。掌握「地址、類型、解參考、層級」四大核心,配合記憶體圖示思考,即可駕馭複雜資料結構與系統程式開發。