可変個引数マクロを究める!(その1)
こんばんは、めのんです。
先日から「私はCが好き」とか「私はCが得意」とか言っているのに、Cの具体的な話題が出てこないのもどうかと考えました。 そんなわけで、今回はガチなCの話題です。
Cには昔からマクロという機能が備わっています。 マクロはプリプロセッサで前処理されて、そのあとに本格的にコンパイルされます。 プリプロセッサには否定的な意見もありますが、良くも悪くもCの特徴的な機能のひとつです。
そんなCのマクロには、関数型マクロという引数を取るものがあります。 具体的には、
#define add(a, b) ((a) + (b))
のように使います。
この引数の数を可変にできるのが可変個引数マクロです。 可変個引数マクロは次のようにして使います。
`#define eprintf(format, ...) fprintf(stderr, (format), VA_ARGS)
このマクロでは、標準エラーに書式化して出力するためのものです。 fpintfを使って素直に書いてもいいのですが、面倒ですからねえ……。
で、ここで登場する「....」の部分が可変個引数です。 可変個引数の展開する場所はVA_ARGSで指定しています。
このVA_ARGSは、マクロに渡した実引数を字面そのままに展開します。 たとえば、
eprintf("%d %d\n", 123, 456);
と書けば、
`fprintf(stderr, ("%d %d\n"), 123, 456);
のようになります。
問題ないのは、「...」の部分に引数をひとつも渡さなかった場合です。 字面通りに展開しますので、
eprintf("hello");
は
`fprintf(stderr, ("hello"), );
のように展開されます。
よく見ないと気付かないかもしれませんね。 最後のカンマが余計なんですよ。 これだとコンパイルエラーになってしまいます。
この問題は結構難問で、解決するのは何らかの工夫が必要になってきます。
具体的な解決方法については、次回でお話ししたいと思います。
それでは!