指標運算是 C 語言核心也最易混淆的部分。本文以 int *p 為例,透過程式碼與執行結果圖解,釐清 *p++、(*p)++、指標加減與位址輸出的關鍵差異。
* 與 ++ 優先序相同,結合方向自右向左,故 *p++ 等價 *(p++):
p 所指值(*p)。p 移向下一個元素(p+1)。int cww[] = {1, 10, 100};
int *a = cww;
printf("*a=%d\n*(a+1)=%d\n*(a+2)=%d\n", *a, *(a+1), *(a+2));
輸出: 1, 10, 100

括號改變優先序:先取值再遞增該記憶體位置的內容,指標本身不變。
int val = 5; int *p = &val; (*p)++; // val 變為 6,p 位址不變
int cww[] = {1, 10, 100};
int *a = cww;
printf("a =%d\na+1 =%d\na+2 =%d\n&(*a)=%d\n", a, a+1, a+2, &(*a));
printf("a =%p (十六進位)\n", (void*)&a);
關鍵觀察:
a+1 位址 = a 位址 + sizeof(int)(通常 4 位元組)。&(*a) 等同 a(解參考再取址回到原位址)。%p 印十六進位位址,%d 印十進位(可能截斷 64 位址)。
| 運算式 | 效果 | 指標是否改變 | 所指值是否改變 |
|---|---|---|---|
*p++ | 取值後指標移下一元素 | 是 | 否 |
*p-- | 取值後指標移上一元素 | 是 | 否 |
(*p)++ | 所指值加 1 | 否 | 是 |
*(p+1) | 取下一元素值 | 否 | 否 |
&(*p) | 取所指變數位址(=p) | 否 | 否 |
*(p+1)、(*p)++,明確語意。p2 - p1 回傳元素個數差,非位元組差。void* 不能直接做指標運算,需轉型為具體型別指標。