TOP >> マニアックなプログラミング
トリッキーコードネット トリッキーなコード

【トリッキーなコード】度肝を抜かれるswapマクロ (C言語)

SWAP(スワップ)とは、 ま~改めていう必要もないぐらい、プログラミングの世界ではありきたりのものじゃないですかね?? ^^;)
SWAPとは、2つの変数内の値を入れ替えっこすることです。

(ほら、Linuxでは、実メモリが足りなくなって、ハードディスクに内容の一部を退避しておく場合、
 そのハードディスク部分を「スワップ領域」って言うでしょ??)


Cではポインタを使用し、こんな関数を実装してみたり、
void swap(int * a, int * b) { int tmp = *a; *a = *b; *b = tmp; }
C++では、参照を使用し、こんな関数を実装してみたり、
inline void swap(int & a, int & b) { int tmp = a; a = b; b = tmp; }
した経験は、たぶんプログラマー歴の長い方ならば、1度や2度はあると思います ^^;) でも、こんなマクロ↓を定義すれば、SWAPの為に、わざわざ別関数を実装しなくても良いって知ってました??
#define swap(a,b) a^=b^=a^=b

Cコード例)

#include <stdio.h> #define swap(a, b) a^=b^=a^=b int main(void) { int i, j; i = 10; j = 20; printf("%d - %d\n", i, j); swap(i, j); printf("%d - %d\n", i, j); return 0; }
結果) swapマクロの実行結果 Oh!見事に値が入れ替わっています。 私は上記のマクロを初めて見たとき、 「スゲ~~!!(*゚∀゚)=3ムッハー 」と思わず叫んでしまいました。 ・・・すいません、嘘です。叫びはしませんでした^^;) でも、かなり驚いたのは間違いないです。 皆さんも機会があれば、このSWAPマクロを使って、同僚をビックリさせちゃいましょう! (「こんなマクロとっくに知ってるよ~」という方は、華麗にスルーしちゃって下さいw) ただし、以下の場合に注意が必要とのこと。
int i = 10; swap(i, i); ASSERT(i == 0);
同一の値を渡した場合は、i^i = 0 の為、i == 0 となり、ASSERTが発動します。 (つまり、iが0になってしまうというオチ) 後、「浮動小数点にこのマクロを使用するとヤバイ」みたいな書き込みがありましたが、 少なくともVC++2005のデフォルト設定では、floatやdouble型の値をこのマクロに渡すと、コンパイルエラーが発生します。

補足:どうして a^=b^=a^=b で値をスワップできるのか?

(2ちゃんねるで、ワザワザAAを作って説明してくれている人がいたので、それを転載します。) C言語swapマクロの説明 C言語swapマクロの説明 非常に分かりやすいです~^^;) おまけ:

浮動小数点でも問題なく動作するSWAPマクロ

#define swap(a,b) {a+=b;b=a-b;a-=b;}

浮動小数点でも問題なく動作するSWAPマクロ その2

#define swap(a,b) {a += b -= (a = b-a);}
トリッキーさには欠けるけれど、上で挙げた様な欠点もないし、浮動小数点をswapしたい場合には、こちらの方が良さげですね^^;) (あ、もちろん、精度の問題とかはありますけど・・・)
トリッキーコードネット の TOPへ HOTNEWS の 総合TOPへ