マクロ関数
たとえばint変数の値を入れ替えるマクロを考える。初めに考えるだろうマクロはこんな感じか
#define SWAP(x, y) int tmp; tmp = x; x = y; y = tmp;
しかし、これだとC89準拠にならない。ブロックの途中で変数の宣言ができない制限があるためだ。よって次の段階ではこうなる。
#define SWAP(x, y) {int tmp; tmp = x; x = y; y = tmp; }
これでほとんどの場合OKなのだが以下のような場合に問題になる。
if (x > 0) SWAP(x, y); else printf("xは正の整数を入力してください");
私はほとんどifの{}は省かないのでまず困らないのだけれど、汎用のライブラリとしては問題がある。ということで、こういう場合の常套手段は以下のマクロ。
#define SWAP(x, y) do {int tmp; tmp = x; x = y; y = tmp; } while(0)
セミコロンをつけることで文になるのは式文、do-while、ジャンプ文であり、do{}while(0)は見た目以外は副作用がないことを利用している。
ところで後輩にこんなマクロじゃダメですか?と質問された。
#define SWAP(x, y) ({int tmp; tmp = x; x = y; y = tmp; })
複文は式では無いので、コンパイルエラーになりそうだが、gccではこれが通った。念のため-ansiオプションをつけたがやはり通る。動作もdo-whileと同じように使える。
文法的に?と思ってbcc32, LSI-C86試食版, VC++Expressで試してみたが全滅だった。gccは懐が広く、先進的なのはいいのだが、オプションつけたら厳密に文法解釈してほしい気がする。