int main(void) {
int a[] = {6, 7, 8, 9, 10};
int *p = a;
*(p++) += 123; // 關鍵行
printf("%d, %d\n", *p, *(++p));
return 0;
}
8, 8
*(p++) += 123; 實際做了什麼?p++ 後置遞增:表達式值為舊 p(指向 a[0]),副作用是 p 指向 a[1]。*p 解引用得到 a[0](值 6)。+= 123 將 a[0] 修改為 129。p 向後移動一個位置;a[0] 被修改但後續未讀取。printf("%d, %d\n", *p, *(++p)); 參數求值順序*(++p):p 從 a[1] 移至 a[2],值為 8,壓棧。*p:p 現指向 a[2],值同為 8,壓棧。printf 彈出並輸出:8, 8。+= 與 = 的陷阱*(p++) += 123; // 原寫法:p 遞增一次,a[0] += 123
*(p++) = *(p++) + 123; // 替換後:p 遞增兩次!a[0] = a[1] + 123
p++ 只求值一次,副作用一次。p++ 各自求值、各自副作用 → p 移動兩格,讀取 a[1] (7) + 123 = 130 寫入 a[0],p 最終指向 a[2]。a[2] 原值 8,經 ++p 指向 a[3] 值 9)。| 知識點 | 說明 |
|---|---|
後置遞增 p++ | 值為舊指針,副作用:指針向後移動一個元素 |
前置遞增 ++p | 副作用先行:指針移動,值為新指針所指內容 |
複合賦值 += | 左運算元只求值一次(C 標準保證) |
| 函數參數求值順序 | C 標準未定義,視編譯器/平台而定(常見右→左) |
| 序列點 | 語句結尾 ;、函數調用前、&& || ?: , 運算符;副作用在序列點前完成 |
printf("%d %d", *p, *(++p)))。warning: operation on 'p' may be undefined。「寫出讓編譯器、讀者、未來的自己都能輕鬆理解的代碼,才是真正的基本功。」