CSAPP 2.10 要求分析無臨時變量的異或交換算法。本文通過真值表逐步推導三條語句如何將 *x、*y 從 a、b 變為 b、a,並說明其數學原理。
void inplace_swap(int *x, int *y) {
*y = *x ^ *y; // 步驟 1
*x = *x ^ *y; // 步驟 2
*y = *x ^ *y; // 步驟 3
}
| 步驟 | *x 值 | *y 值 | 說明 |
|---|---|---|---|
| 初始 | a | b | 假設 *x 指向 a,*y 指向 b |
1: *y = *x ^ *y | a | a ⊕ b | *y 變為 a^b,*x 仍為 a |
2: *x = *x ^ *y | a ⊕ (a ⊕ b) = b | a ⊕ b | 利用結合律:a^(a^b) = (a^a)^b = 0^b = b |
3: *y = *x ^ *y | b | b ⊕ (a ⊕ b) = a | *y = b^(a^b) = (b^b)^a = 0^a = a |
a ^ b == b ^ a(a ^ b) ^ c == a ^ (b ^ c)a ^ a == 0a ^ 0 == a正是這四條性質,保證了三步異或操作能在不引入臨時變量的情況下完成交換。
若 x == y(別名),步驟 1 即將該地址值置 0,後續全為 0。這正是 CSAPP 2.11 奇數長度數組反轉失敗的根因。
GCC/Clang/MSVC 在優化等級 -O2 以上時,會將「臨時變量交換」優化為寄存器 XCHG 指令或等效移動序列,性能不劣於異或交換,且無別名風險、可讀性高。因此:
工程實踐建議:優先寫
tmp = *x; *x = *y; *y = tmp;,讓編譯器做優化。
異或交換是位運算經典教學案例,展示了布爾代數在計算機系統中的巧妙應用。理解其推導過程有助於深入掌握位級操作,但實際項目中請使用臨時變量版本。