はじめての C

[Learning GNU C]

10.4. マクロへの 警告 caveat

マクロは まちがった 使い方が できる。 コードが コンパイルを 始めると もはや マクロは 存在しないので バグを つかまえるのは 困難だ。 小さな 例題を 取り上げよう。

Example 10-2. max_macro.c

#define MAX(a, b) (a > b ? a : b)

int
main()
{
int cows = 10, sheep = 12;

printf("We have %d of our most common animal.\n", MAX(cows, sheep));

return 0;
}

コンパイルし 実行すると (下の 出力が) 得られる。

ciaran@poor:~/book$ ./max_macro
We have 12 of our most common animal.
ciaran@poor:~/book$

そう、全て 良好に 見える。 次の 例題を 試してみよう。

Example 10-3. max_macro_problem.c

#define MAX(a, b) (a > b ? a : b)

int
main()
{
int cows = 10, sheep = 12;

printf("We have %d of our most common animal.\n", MAX(cows, sheep));

printf("Hang on, we just bought another one.\n");
printf("Now we have %d.\n", MAX(cows, ++sheep));

return 0;
}

なにが 起きるかが わかるだろうか?

ciaran@poor:~/book$ ./max_macro_problem
We have 12 of our most common animal.
Hang on, we just bought another one.
Now we have 14.
ciaran@poor:~/book$

text の 置き換えが 生じると "++sheep" が 2度 要求 instance される。 別の もっと 意地の悪い 方法では マクロへの 引数として 関数が 使われ (コードに) 渡されて その正体を 現わすだろう。 この関数で global または static 変数を 変更すれば 変更が 2度 multiple times 生じるだろう。 これらの バグは 見つけるのが とても 困難だ。 コードは 完全に 有効なので コンパイラは 全く 警告を しない。 このバグは 実行時にのみ 見つかり マクロが 呼び出され それが 副作用を もつ 引数を 伴う 場合にだけ 起きる 習性 wont を もつ。