マクロの隙間2011年02月16日 21時37分28秒

実は C/C++ のマクロには落とし穴が隠されている。非常に小さな隙間なのだが、落ちると大きな怪我をすることになる。

#define VAR1 ( arg1 )
#define VAR2( arg2 )

この二つは似て非なるものだ。この穴は時折見つけづらく、余計な時間を浪費することになる。VAR の後の微妙な隙間が大きな違いをもたらす。

VAR1 は置換。ここでは、VAR1 を ( arg1 ) に書き換える。括弧は、マクロの記述で、展開時にも意図した順になるように推奨されている。

VAR2 はマクロ関数。VAR2 は arg2 を引数として取り、その後に続く、式に展開される。ここでは、VAR2 の後に何もないので空文になる。

実際に試してみる。


% cat macro.c 
#define VAR1 ( arg1 )

VAR1( 2 )

#define VAR2( arg2 )

VAR2( 4 )
% cpp macro.c 
# 1 "macro.c"
# 1 "<built-in>"
# 1 "≷command-line>"
# 1 "macro.c"


( arg1 )( 2 )





この例では、マクロ自体は不正ではなくエラーは出ない。コンパイラを通すとこの例ではもちろんエラーになる。

運悪くこの全く異った置換が成功してしまう事もある。コンパイルに失敗すると、意味の不明なエラーに悩まされる。大概にして、奇妙な行数から出て、一見すると間違っていないように見える。だから発見が難しい。たった一つの空白が犯す罪を。

更に運が悪いとコンパイルまで通ることもある。不思議な挙動に悩まされる事になる。デバッガもマクロの追跡はまともに出来ないし、実はマクロの所為で普段とは違ったステップを行なっていたとしても、甚だ見つけづらい。