| 運算式 | 結合方向 | 實際意義 | 影響對象 |
|---|---|---|---|
*p++ | 右向左 | *(p++) | 指標 p 移動,解參考值不變 |
++*p | 右向左 | ++(*p) | 指標指向的值遞增,p 不動 |
(*p)++ | 左向右 | 先解參考,後遞增值 | 指標指向的值遞增(後置),p 不動 |
*++p | 右向左 | *(++p) | 指標 p 先遞增,再解參考新位址 |
關鍵規則:* (解參考) 與 ++/-- (前置/後置) 同優先級,**結合方向皆為右向左**。括號 () 可強制改變順序。
i++ vs ++iint i = 1;
printf("i++ = %d\n", i++); // 輸出 1,i 變 2
printf("i = %d\n", i); // 輸出 2
int j = 1;
printf("++j = %d\n", ++j); // 輸出 2,j 變 2
printf("j = %d\n", j); // 輸出 2
結論:後置 i++ 遇分號才生效;前置 ++j 立即生效。printf 參數求值順序依編譯器而定(通常右向左),切勿在單一語句中對同一變數多次副作用操作(未定義行為)。
*p++ 解析int i = 10;
int *p = &i;
int v = *p++; // 等價 v = *(p++)
printf("*p = %d\n", *p); // 輸出 10 (p 已指向下一個位址,內容未知/垃圾值)
printf("v = %d\n", v); // 輸出 10 (舊位址的值)
printf("i = %d\n", i); // 輸出 10 (i 未變)
現象:++ 作用於 p,* 取舊位址值。p 移動,i 不變。
++*p 解析int i = 10;
int *p = &i;
int v = ++*p; // 等價 v = ++(*p)
printf("*p = %d\n", *p); // 輸出 11
printf("v = %d\n", v); // 輸出 11
printf("i = %d\n", i); // 輸出 11 (i 被修改)
現象:++ 作用於 *p (即 i),p 不動。
*++p 解析int arr[2] = {10, 20};
int *p = arr;
int v = *++p; // 等價 v = *(++p)
printf("*p = %d\n", *p); // 輸出 20 (p 指向 arr[1])
printf("v = %d\n", v); // 輸出 20
現象:p 先遞增,再解參考新位址。
(*p)++ 解析int i = 10;
int *p = &i;
int v = (*p)++; // 後置遞增值
printf("*p = %d\n", *p); // 輸出 11
printf("v = %d\n", v); // 輸出 10 (舊值)
printf("i = %d\n", i); // 輸出 11
現象:值遞增但回傳舊值,p 不動。
++:*p++ → p++ 緊貼 → p 動;++*p → *p 緊貼 →值動。(*p)++ 強制先解參考,再對值後置遞增。++*p 前置在 * 左;*p++ 後置在 p 右。v = *p; p++; 或 ++(*p);,可讀性大增const:const int *p (值不可改) vs int *const p (指標不可改),編譯器會攔截錯誤while (*p) { ...; p++; } 或 for (; *p; p++),語意清晰指標運算符優先級看似迷霧,實則遵循簡單規則:**同級右結合,括號改順序**。掌握 *p++ (移指標)、++*p (改值)、(*p)++ (改值後置)、*++p (移指標再取值) 四種核心模式,即可應對 99% 場景。實務中請寫給人看的代碼——適度使用括號、拆分語句、加上註解,比炫技巧更專業。