#define 展開を沢山一気に確認+整形をプログラムでやらせるときに注意する点について
Tchar.h generic-text mapping cheatsheet
を作るときに問題となったのが、
「C言語の #define
展開を沢山一気に確認するにはどうすればよいか?」
ということである。
もっとも一個一個ならばIDE上でマウスホーバーすれば展開表示されるので このようなことを思う必要はない。

#define
展開表示そこでコンパイラによって実際に展開させることにした。 コンパイラのプリプロセッサ展開だけをさせることも考えたが、 出力の整形も一気にやらせることを考えたので 普通にC言語のプログラムを書くことにした。
このとき一つ注意が必要だったので、備忘録としてメモっておく。
#define FOO bar
printf("%s", FOO);
これはコンパイラによって下記のように展開される(C言語として妥当ではないのでプリプロセッサ処理まででコンパイルエラーになる)
printf("%s", bar);
今したいのはこの展開後を「テキスト」として取得したいので
ここでマクロの #
を使うことにした。
#define STRINGIFY(x) (#x)
#define FOO bar
printf("%s", STRINGIFY(FOO));
しかし実はこれは予期する動作にならず、 下記のようになる:
printf("%s", ("FOO"));
展開させつつ、テキストに変換するにはマクロを二重にする必要があるらしい。
#define STRINGIFY_(x) (#x)
#define STRINGIFY(x) (STRINGIFY_(x))
#define FOO bar
printf("%s", STRINGIFY(FOO));
これで望んだ展開がやっと得られる。
printf("%s", (("bar")));
逆に言えば、 #
を含むマクロを間接的に呼んだ場合、
実際に書かれたものと違って展開されてしまうので
注意が必要ということになる。
#define STRINGIFY0(x) (#x)
#define STRINGIFY1(x) (STRINGIFY0(x))
#define STRINGIFY2(x) (STRINGIFY1(x))
#define FOO BAR
#define BAR baz
printf("%s", STRINGIFY0(FOO));
printf("%s", STRINGIFY1(FOO));
printf("%s", STRINGIFY2(FOO));
printf("%s", STRINGIFY0(BAR));
printf("%s", STRINGIFY1(BAR));
printf("%s", STRINGIFY2(BAR));
↓
printf("%s", ("FOO"));
printf("%s", (("baz")));
printf("%s", ((("baz"))));
printf("%s", ("BAR"));
printf("%s", (("baz")));
printf("%s", ((("baz"))));