第12問の答え

答え

マクロの定義に括弧が付いていないのが間違い!
#define VALUE_FOR(X) 2 * X + 1
マクロの定義では数式全体と引数を括弧で囲むのが正解!
#define VALUE_FOR(X) (2 * (X) + 1)

解説

これは、マクロの定義方法に関する出題でした。問題のプログラムでは、期待どおりにマクロが展開されません。

マクロの部分がどういう風に展開されるか分かるかしら?
はーい。やってみます!
えっと、マクロの部分というのはここだな。
VALUE_FOR(2 + 3)
これが2 * X + 1に展開されるとき、X2 + 3に置き換わるから……
2 * 2 + 3 + 1
ね、11になると思ったのに、8になっちゃったでしょ。
あ!ほんとですね。
2 + 3を括弧で囲まないと、思ったとおりの計算にならないわね。
そっか。ここに括弧が必要なんだ!
2 * (2 + 3) + 1
つまり、マクロ定義のX(X)にすればいいんですね!
おしい!

マクロの定義には、展開されるときのことを考えて括弧を付けておく必要があります。今回のプログラムでは、次のように引数に括弧を付ければ期待どおりの結果が得られることが分かりました。

#define VALUE_FOR(X) 2 * (X) + 1

でも、実はそれだけでは足りません。マクロ定義では数式全体も、このように括弧で囲む必要があります。

#define VALUE_FOR(X) (2 * (X) + 1)

なぜ全体を括弧で囲む必要があるのかは、次の例で考えれば理解できるでしょう。

  printf("Value is %d\n", VALUE_FOR(2 + 3) * 2);
この場合、結果が22になるのが正しいわね。
ですね。そうなるかどうか、確認してみます!
この部分に(2 * (X) + 1)を当てはめて展開すると……
VALUE_FOR(2 + 3) * 2
括弧が付いて、こうなる!
(2 * (2 + 3) + 1) * 2
なるほど!ちゃんと22になりますよ。
もしマクロに全体を囲む括弧がなかったら、結果が変わってしまうのが分かるかしら?
はい。うしろの1 * 2が先に計算されて、12になっちゃいますね。

このように、マクロで数式を定義するときは引数と全体を括弧で囲むのが鉄則です。括弧を付け忘れると予想外の動作になってしまうこともあるので、できる限り注意しましょう。

ちなみに、どうしてもミスをしやすいところなので、「マクロは極力使うべきではない」という考え方もあります。とくに必要性がない限り関数を使うようにするのも、厄介ごとを避ける一つの方法です。

ここがポイント!
マクロを定義するときは、引数と数式全体の両方に括弧を付けよう!

修正後のプログラム

main.c
#include <stdio.h>
#include <stdlib.h>

#define VALUE_FOR(X) (2 * (X) + 1)

int main(void) {
  printf("Value is %d\n", VALUE_FOR(2 + 3));

  return EXIT_SUCCESS;
}
実行結果
Value is 11