2015年12月8日火曜日

C言語の__LINE__を文字列リテラル化したい

C言語の__LINE__は、そのファイルの中での行数を表す整数リテラルに展開される組み込みマクロ。それを文字列として扱うにはどうするかという話。

文字列に変換しようとしたらsprintf, snprintfを使うのが、まあ普通だろう。

sprintf(buf, "%d", __LINE__);
ただ、これは別途バッファを用意する必要があるし、デカくて重たいprintf系の関数は使いたくない(特に組み込みでは)。それに、コンパイル時に結果が一意に定まるはずの変換を動的にやらされるのは癪だ。

そこで使えるのが、プリプロセッサの文字列化演算子#。#stringを"string"に置換してくれるナイスガイ。ただ、__LINE__との併用は一筋縄ではいかず、

#__LINE__
#(__LINE__)
とか記述してもエラーになってしまう。
#define TO_STRING(arg) #arg

TO_STRING(__LINE__)
とマクロ化しても、これでは"__LINE__"になってしまう。正解は、マクロの引数として__LINE__だけ展開させてから、文字列化マクロに食わせるという、非常にまどろっこしい方法。
#define TO_STRING(arg) #arg
#define NUM2STR(num) TO_STRING(num)

NUM2STR(__LINE__)
これなら"10"とか"666"のような、""で括って文字列リテラル化した行数になる。あくまで文字列リテラルなので、
__FILE__ ":" NUM2STR(__LINE__)
みたいに記述して、コンパイル時に静的に文字列の結合もしてもらえる。

0 件のコメント:

コメントを投稿