8.5 文字列化
8.5.1 マクロ関数と文字列化演算子
#define で作成したマクロ関数だけに指定することができるプリプロセッサ演算子に、パラメータで受け取ったトークン列を文字列に変換する演算子があります。これは、与えられたトークン列を解析し、二重引用符を付加した形に展開します。こうすることによって、数値やトークン列を自動的に文字列化するマクロ関数などを作成することができるでしょう。
トークン列を文字列化するには、マクロ関数の仮パラメータの前に # 演算子を指定します。例えば、次のように記述すれば関数は与えられた引数を文字列化します。
#define TOSTRING(param) #param
これはマクロ関数なので param に渡されるトークン列の型などを規制することはできません。しかし、param のトークン列がどのようなものであれ # 演算子はそのトークン列を文字列化します。その関係は次のようなものとなるでしょう。
TOSTRING(1234) → "1234"
TOSTRING(int iValue = 10\n) → "int iValue = 10\\n"
TOSTRING("Kitty") → "\"Kitty\""
これらの変換は、コンパイル前のソーステキストレベルで展開されることに注意してください。プログラム実行時に動的に変換されるものではありません。文字列化演算子は、トークン列内の二重引用符 " は \" に変換し、円記号 \ は \\ に変換されます。こうすることによって、トークン列を確実にそのままの形で文字列化することができます。
#include <stdio.h> #define PRINTLN(string) printf(#string "\n") int main() { PRINTLN(0xFF); PRINTLN(Kitty on your lap); PRINTLN(Kernighan and Ritchie wrote "hello, world\n" on their book.); return 0; }
コード1の PRINTLN() マクロ関数は、引数で指定したトークン列を文字列として printf() 関数で表示します。最初の二つは、そのまま文字列化されていることが確認できます。面白いのは最後の長文で "hello, world\n" というトークンが文字列化されているところです。これらの文字列はプリプロセッサによって \"hello, world\\n\" に変換されているのです。そのため、二重引用符やエスケープ文字がそのまま表示されているのです。