核心運算符
1. & —— 取址運算符
- 作用:獲取變數的記憶體位址
- 操作數:左值(變數、陣列元素、結構成員等)
- 結果:指向該類型的指標
2. * —— 三重身份
| 語境 | 含義 | 範例 |
| 宣告中 | 指標宣告標識 | int *p; |
| 表達式右值 | 間接存取(取值) | int x = *p; |
| 表達式左值 | 間接賦值(修改所指物件) | *p = 10; |
| 兩運算元皆為算術值 | 乘法運算符 | a * b |
合法與非法操作範例
int a, b = 20, c = 30, d = 40, *p;
p = &d; // 合法:p 指向 d
a = *p; // 合法:取 p 指向的值 (40) 給 a
*p = c; // 合法:將 c (30) 存入 p 指向的位置 (d 變為 30)
*p = &b; // 錯誤:左邊是 int,右邊是 int*,類型不匹配
核心等價表達式(指標 p 指向變數 a:int a = 20, *p = &a;)
| 表達式 | 等價形式 | 說明 |
*p | a | 間接存取等於直接存取 |
p | &a | 指標值等於變數位址 |
&*p | &a / p | 取值後取址回到原位址 |
*&a | *p / a | 取址後取值回到原值 |
(*p)++ | a++ | 後置遞增所指物件 |
(*p)-- | a-- | 後置遞減所指物件 |
++(*p) | ++a / ++*p | 前置遞增所指物件 |
--(*p) | --a / --*p | 前置遞減所指物件 |
優先級關鍵:*p++ vs (*p)++
int arr[] = {10, 20, 30};
int *p = arr;
*p++ // 等價 *(p++):取 arr[0]=10,p 指向 arr[1]
(*p)++ // 取 arr[0]=10,arr[0] 變為 11,p 不動
++*p // 等價 ++(*p):arr[0] 變為 11,取值 11
*++p // 等價 *(++p):p 指向 arr[1],取值 20
記憶體模型視覺化
記憶體位址: 0x1000 0x1004 0x1008
+------+ +------+ +------+
int a = 20: | 20 | (a 位於 0x1000)
+------+
int *p = &a: p 儲存 0x1000 (p 自身位於某位址,如 0x2000)
*p: 解引用 p -> 存取 0x1000 -> 得到 20
&a: 取 a 位址 -> 0x1000
&*p: 解引用 p -> 0x1000 -> 取址 -> 0x1000
*&a: 取 a 位址 -> 0x1000 -> 解引用 -> 20
實務建議
- **括號明確意圖**:
(*p)++ 而非 *p++ 當要修改所指值
- **const 正確性**:
const int *p (指向常量) vs int *const p (常量指標)
- **避免多層間接**:
***ppp 難以閱讀,重構為結構體或中間變數
- **編譯器警告**:開啟
-Wall -Wextra -pedantic 捕獲指標類型不匹配
總結
& 與 * 是互逆操作:&*p == p、*&a == a。掌握它們的優先級、結合性、左值/右值語境,是寫出正確、無歧義指標代碼的基礎。