&(取址)與 *(解引用/間接訪問)是指針運算的陰陽兩面。掌握它們的結果類型、指向類型、佔用地址三大屬性,是寫出正確指針代碼的基石。
| 運算 | 結果類型 | 指向類型 | 佔用地址 |
|---|---|---|---|
&a | typeof(a)*(在 a 類型後加 *) | typeof(a) | &a(a 的地址) |
*p | typeof(*p)(p 指向的類型) | typeof(*p) | p(p 存儲的地址) |
int a = 5;
int b;
int *p;
int **q;
p = &a; // &a: 類型 int*, 指向 int, 地址 = &a
*p = 10; // *p: 類型 int, 地址 = p (=&a) → 相當於 a = 10
q = &p; // &p: 類型 int**, 指向 int*, 地址 = &p
*q = &b; // *q: 類型 int*, 地址 = q (=&p) → 相當於 p = &b
**q = 34; // *q 是 int*, **q 是 int, 地址 = *q (=&b) → 相當於 b = 34
#include
int main() {
int a = 5, b;
int *p; int **q;
printf("a = %d\n", a); // 5
p = &a; *p = 10;
printf("a = %d\n", a); // 10
q = &p; *q = &b; **q = 34;
printf("b = %d\n", b); // 34
return 0;
}
輸出:
a = 5
a = 10
b = 34
& 加星,* 去星。&a 的值是 &a;*p 的地址是 p。**q = *(*q),先解外層得指針,再解內層得值。| 錯誤代碼 | 問題 | 修正 |
|---|---|---|
int *p = a; | a 是 int,非地址 | int *p = &a; |
*p = &a; | *p 是 int,不能存地址 | p = &a; |
int **q = &a; | 類型不匹配:&a 是 int* | int *p = &a; int **q = &p; |
const int *p1; // *p1 是 const int,不可通過 *p1 修改值
int *const p2; // p2 本身是 const 指針,不可修改 p2 指向
const int *const p3; // 雙重 const
讀法同樣遵循「從右向左」:int *const p2 → p2 is a const pointer to int。
& 與 * 是互逆運算:*(&a) == a、&(*p) == p(前提 p 有效)。
只要牢記 「結果類型、指向類型、佔用地址」三元組,任意級指針推導皆可機械化、零失誤。