【C言語入門】変数の値を交換する:作業用変数を使わない「差分利用」のアルゴリズム
2つの変数の値を入れ替える際、通常は「tmp(一時的な変数)」という第3の箱を用意しますが、今回はあえて「差分」を利用して、2つの変数だけで完結させるトリッキーな手法を解説します。
1. 実践:足し算・引き算による入れ替え
【 動作確認 】 以下のコードは、`a` と `b` の差を計算し、その結果を中継地点とすることで値を交換しています。`calc_swap.c` として保存して実行してみてください。
int main(void) {
int a = 10;
int b = 3;
printf("初期状態: a=%d, b=%d\n", a, b);
// 1. aとbの「差」をbに保存
b = a - b; // b = 10 - 3 = 7
printf("ステップ1: a=%d, b=%d\n", a, b);
// 2. 元のaから「差」を引いて、新しいaにする
a = a - b; // a = 10 - 7 = 3 (入れ替え完了1)
printf("ステップ2: a=%d, b=%d\n", a, b);
// 3. 新しいaに「差」を足して、新しいbにする
b = b + a; // b = 7 + 3 = 10 (入れ替え完了2)
printf("最終状態: a=%d, b=%d\n", a, b);
return 0;
}
2. アルゴリズムが適用できる型と注意点
【 技術的解説 】 この手法は数値計算に基づくため、適用できる型や制約に注意が必要です。
・整数型 (int, char, longなど):符号の有無にかかわらず動作します。
・浮動小数点型 (float, double):理論上は動作しますが、微小な計算誤差が発生する可能性があるため推奨されません。
★ 重大な注意点(オーバーフローのリスク):
・計算の途中で、その型が保持できる最大値(INT_MAXなど)を超えてしまうオーバーフローが発生するリスクがあります。C言語の規格上、符号付き整数のオーバーフローは「未定義の動作」となり、予期せぬ挙動を引き起こす可能性があります。
3. 技術的背景:なぜこのコードが生まれたのか
現代のコンピュータではメモリも豊富にあり、作業用変数を使う `tmp = a; a = b; b = tmp;` の方が可読性も高く安全です。しかし、メモリが極めて限られていた時代や、特殊なCPU命令を最適化したい場面などでは、このような「メモリを節約する工夫」が重宝されてきました。
4. 理解度チェック!練習問題
【 復習問題 】 今回紹介したアルゴリズムで、int型の変数 `a` と `b` の値を交換する際に発生しうる最も深刻なリスクはどれでしょうか?
選択肢:
A. 計算に時間がかかりすぎる。
B. 計算の途中で数値が型の最大範囲を超え、オーバーフローが発生する。
C. printf関数で表示できなくなる。
D. C言語の最新規格(C17)では禁止されている。
正解と解説を見る
正解:B
大きな値同士の計算では、途中の加減算で型の限界(オーバーフロー)を超える可能性があります。パズル的な面白さはありますが、安全性を優先する現代のプログラミングでは、一時変数を使う方法が一般的です。
5. まとめ
「差分を利用して値を入れ替える」という発想は、変数の値を単なるデータではなく「状態の差」として捉える面白いアルゴリズムです。実務での利用には注意が必要ですが、こうした低レイヤのテクニックを知ることで、メモリと演算の仕組みに対する理解がより深まります。