指標運算是 C/C++ 靈活操作記憶體的核心,亦是缺陷高發區。本文系統梳理指標的賦值、加減、關係、取址/取值運算,並以 32 位元環境為基準說明位元組位移規則,助你建立精確的心智模型。
| 形式 | 範例 | 說明 |
|---|---|---|
| 初始化 | int a; int *ip = &a; | 宣告時指定地址 |
| 變數地址賦值 | int a; int *ip; ip = &a; | 同型別變數地址 |
| 指標間賦值 | int *pa = &a; int *pb; pb = pa; | 同型別指標互賦 |
| 陣列首址賦值 | int a[5], *pa; pa = a; // 或 pa = &a[0] | 陣列名退化為首元素地址 |
| 字串常值賦值 | char *pc = "c language"; | 指向唯讀字串字面值區 |
| 函式入口賦值 | int (*pf)(); pf = func; | 函式指標指向程式碼區 |
設 ip 指向型別 T 的陣列元素:
ip + n / ip - n:向前/後移動 n × sizeof(T) 位元組。ip++ / ++ip / ip-- / --ip:移動一個元素距離(sizeof(T) 位元組)。char a[20];
int *ip = (int*)a; // 指向 a[0..3] 四個位元組
ip++; // ip += sizeof(int) = 4,指向 a[4..7]
ip += 5; // ip += 5 * 4 = 20,指向 a[20..23](已超出陣列)
關鍵規則:指標運算以「元素個數」為單位,編譯器自動乘上 sizeof(指向型別) 換算位元組位移。
== != < > <= >=,比較的是記憶體位址高低。0(或 NULL)比較:ip == 0 表示空指標,ip != 0 表示有效指標。& 與取值 * 運算子| 運算子 | 功能 | 結合性 | 範例結果 |
|---|---|---|---|
& | 取變數位址 | 右向左 | &a 型別 int*,指向 int |
* | 取指標指向內容 | 右向左 | *p 型別 int,佔用 p 指向位址 |
int a = 12, b;
int *p = &a; // p: int*, 指向 a
int **ptr = &p; // ptr: int**, 指向 p
*p = 24; // 修改 a = 24
*ptr = &b; // 修改 p 指向 b
**ptr = 34; // 修改 b = 34
區別:宣告中的 * 是型別修飾符;表達式中的 * 是解參考運算子。
[]、() > *(左結合)。int (*p)[5]; // p 是指向 int[5] 的指標
int *p[5]; // p 是 int* 陣列(5 個 int 指標)
int (*func)(); // func 是指向函式的指標
int *func(); // func 是回傳 int* 的函式
最終結果為指標的表達式即指標表達式,具備四要素:指標型別、指向型別、指向記憶體區、指標自身記憶體。所有指標運算均在這四要素框架內進行。
系列導航:(一) 指標概念與四要素 | (二) 記憶體管理與野指標防禦 | (三) 指標運算 | (四) 進階應用與陷阱