語法與語義
- `a %= b` 等價於 `a = a % (b)` (b 以括號包裹,先求值)。
- 左操作數必須為可修改左值 (變數、解引用指標、陣列元素)。
- 結果類型為左右操作數經常用算術轉換後的類型。
- 副作用:修改左操作數值,序列點在語句結束 (或 `,`、`&&`、`||`、`?:` 之前)。
優先級與結合性
所有復合賦值運算符 (`= += -= *= /= %= &= ^= |= <<= >>=`) 具有相同優先級,**右結合性**。
優先級順序 (高→低):
`()` `[]` `->` `.` → 後綴 `++` `--` → 單目 `++` `--` `+` `-` `!` `~` `*` `&` `(type)` `sizeof` `_Alignof` → `*` `/` `%` → `+` `-` → `<<` `>>` → `<` `<=` `>` `>=` → `==` `!=` → `&` → `^` → `|` → `&&` → `||` → `?:` → 賦值/復合賦值 (右結合) → `,`。
多重復合賦值鏈式求值實例
int a = 10, b = 3;
// a += b %= a - b
// 步驟 1: 先算最右邊復合賦值 b %= (a - b)
// a - b = 7
// b = b % 7 = 3 % 7 = 3 (b 變為 3)
// 步驟 2: 再算左邊 a += (b) // 此處 b 為步驟1結果 3
// a = 10 + 3 = 13
// 最終: a=13, b=3
常見陷阱
- 浮點數取模: `%` 僅適用於整數類型。浮點取模用 `fmod` / `remainder` (``)。
- 負數取模符號: C99 規定 `a % b` 與 `a` 同號 (截斷向零除法)。`-7 % 3 = -1`,`7 % -3 = 1`。Python/數學定義不同 (同除數號)。
- 除零未定義行為: `a %= 0` → UB,程式可能崩潰或產生任意結果。必須檢查除數非零。
- 副作用順序未定義: `a[i++] %= a[i++]` → UB (同一標量對象在兩個序列點之間被修改多次)。
- 類型提升陷阱: `unsigned char c = 200; c %= 150;` → `c` 先提升為 `int` 運算,結果 50 再截斷存回 `unsigned char`,正確。但 `signed char c = -10; c %= 3;` → 實現定義行為 (負數右移/取模)。