BohYoh.comトップページへ
C & C++ FAQ
目次

C C++ 二つの変数値を交換する関数形式マクロはどう実現すればよいでしょうか。

 型typeをもつ二つの変数値を交換する関数形式マクロswapは、次のように定義しましょう。
  #define swap(type, x, y) do {type t; t=x; x=y; y=t; } while (0)

 なお、次のように定義している書籍があるようですが、これはお薦めできません。というのも、このswapは有効に使えない局面があるからです。
  #define swap(type, x, y) {type t; t=x; x=y; y=t; }
その理由を考えましょう。左下のif文は右下のように展開されます。
if (na > nb)
    swap(int, a, b);
else
    swap(int, a, c);
if (na > nb)
    { type t = na;  na = nb;  nb = t; } ;
else
    { type t = nb;  nb = na;  na = t; } ;
 if文は、以下のいずれかの形式をもちます。
  if (式) 文
  if (式) 文 else 文
したがって、最初の文の後にelseがあれば、後者の形式とみなされ、そうでなければ前者の形式とみなされ、そこでif文は終了となります。さて、この場合、na > nbが成立したときに実行されるのは、{から}までの複合文であっり、網掛け部が前者のif文とみなされます。
if (na > nb)
    { type t = na;  na = nb;  nb = t; } ;
else
    { type t = nb;  nb = na;  na = t; } ;

if (na > nb)
    複合文 空文
else
    複合文 空文

if (na > nb) 文 文 else 文
if文            文 else 文
この直後にelseが位置すべきですが、セミコロンが蛇足となってしまいます(セミコロンだけの文である空文とみなされます)。
if (na > nb)
    swap(int, a, b)
else
    swap(int, a, c)
 したがって、どうしてもこのマクロを使いたいのであれば、右のように、セミコロンを抜かなければなりません。…でも、これは、どうみてもC言語のプログラムらしくありませんし、ついついセミコロンを付けたときはエラーとなります。

 さて、最初に示したswapを用いると、右のように展開されます。
if (na > nb)
    swap(int, a, b);
else
    swap(int, a, c);
if (na > nb)
    do { type t = na;  na = nb;  nb = t; } while (0);
else
    do { type t = nb;  nb = na;  na = t; } while (0);
whileに続く( )中の式の値は0ですから、{ }で囲まれた部分が実行される(繰り返される)のは、1回限りです。また、do文は、
  do 文 while (式);
という形式をもっていますので、構文的に次のように解釈され、全く問題がないのです。
if (na > nb)
    do { type t = na;  na = nb;  nb = t; } while (0);
else
    do { type t = nb;  nb = na;  na = t; } while (0);
if (na > nb)
    while文
else
    while文

if (na > nb) 文 else 文
if文            else 文

戻る

BohYoh.comロゴ