首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言變數交換的四種經典方法:從臨時變數到位運算與堆疊技巧

     編輯:關於C語言

問題:交換兩個變數 a、b 的值

方法一:臨時變數(最通用、最安全)

int a, b, t;
scanf("%d %d", &a, &b);
t = a; a = b; b = t;
printf("%d %d\n", a, b);
  • ✅ 適用所有型別(整數、浮點、結構體、指標)
  • ✅ 無溢位風險、無副作用
  • ✅ 編譯器優化極佳(常優化為寄存器交換)
  • ⚠️ 需額外儲存空間(可忽略不計)

方法二:算術運算(無臨時變數,整數適用)

int a, b;
scanf("%d %d", &a, &b);
a = a + b;  // a = a₀ + b₀
b = a - b;  // b = (a₀ + b₀) - b₀ = a₀
a = a - b;  // a = (a₀ + b₀) - a₀ = b₀
printf("%d %d\n", a, b);
  • ⚠️ 溢位風險:a + b 可能超出型別範圍(有號整數溢位 = UB)
  • ⚠️ 僅適用數值型別,不適用指標/結構體
  • ⚠️ 現代編譯器優化下不比臨時變數快

方法三:位元 XOR 交換(無臨時變數、無溢位)

int a, b;
scanf("%d %d", &a, &b);
a ^= b;  // a = a₀ ⊕ b₀
b ^= a;  // b = b₀ ⊕ (a₀ ⊕ b₀) = a₀
a ^= b;  // a = (a₀ ⊕ b₀) ⊕ a₀ = b₀
printf("%d %d\n", a, b);
  • ✅ 無溢位、位級操作
  • ⚠️ 同一變數交換失效:swap(x, x) 導致歸零
  • ⚠️ 僅適用整數型別
  • ⚠️ 現代 CPU 流水線下較慢(相依鏈長)

方法四:直接輸出交換(僅顯示需求)

int a, b;
scanf("%d %d", &a, &b);
printf("%d %d\n", b, a);  // 不修改變數,僅交換輸出順序
  • ✅ 最簡潔、零開銷
  • ⚠️ 僅適用「只需輸出交換結果」的場景
  • ⚠️ 變數本身值未變,後續使用仍為原值

方法五:堆疊/汇編視角(教學用)

/* 概念示意 */
push a
push b
pop  a  // a 獲取原 b
pop  b  // b 獲取原 a
  • 函數呼叫慣例中實際發生:參數入棧、返回值出棧
  • 內聯汇編可直接操作:xchg 指令 (x86)

綜合對比表

方法適用型別溢位風險同變數安全可讀性推薦度
臨時變數所有無✅⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
算術加減數值高✅⭐⭐⭐⭐⭐
XOR 位運算整數無❌⭐⭐⭐⭐
輸出交換所有無N/A⭐⭐⭐⭐情境專用
std::swap / 內建所有無✅⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐ (C++)

現代最佳實踐

  • C:使用臨時變數,或封裝為 #define SWAP(t, a, b) { t tmp = a; a = b; b = tmp; }
  • C++:std::swap(a, b)(泛型、移動語意、ADL、特化優化)
  • 編譯器優化:-O2 下臨時變數交換常優化為寄存器 xchg 或重命名,零記憶體存取
  • 避免花招:XOR/算術交換在現代架構上不比臨時變數快,且引入風險

經典面試陷阱題

void swap(int *a, int *b) {
    *a ^= *b;
    *b ^= *a;
    *a ^= *b;
}
int x = 5;
swap(&x, &x);  // x 變為 0!生產代碼禁用 XOR swap
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved