前提
Cのリテラル文字列は2つ続けて書くと連結してくれる。
1 2 3 4 5 6 7 |
const char* p = "abc" "xyz"; // p is "abcxyz" #define ABC "abc" #define XYZ "xyz" const char* q = ABC XYZ; // q is "abcxyz" |
マクロ
ここでL”abcxyz”がほしいときは以下のようにする。
1 2 3 4 |
#define TO_LSTRINNER(x) L ## x #define TO_LSTR(x) TO_LSTRINNER(x) const wchar_t* wp = TO_LSTR(ABC) TO_LSTR(XYZ); |
2重のマクロにしないとならない。1重にすると以下のように解釈される
1 |
const wchar_t* wp = TO_LSTRINNER(ABC); |
これは以下のように展開される。
1 |
const wchar_t* wp = LABC; |
つまりマクロを一回かますと、マクロが展開されることになる。##は連結するがシンボルとかを意識しないので単に結びつける、マクロを一回かまさないと展開されないのでLABCになってしまう。このLABCがどこかで#defineされていればちゃんと展開される。
#
ちなみにマクロの#は文字列にして展開してくれるので以下のように書くこともできる。もっと良い書き方があるのかよくわからない。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#define ABC abc #define XYZ xyz #define TO_STRINNER(x) #x #define TO_STR(x) TO_STRINNER(x) #define TO_LSTRINNERINNER(x) L ## x #define TO_LSTRINNER(x) TO_LSTRINNERINNER(#x) #define TO_LSTR(x) TO_LSTRINNER(x) #endif int main() { const char* q = TO_STR(ABC) TO_STR(XYZ); // q is "abcxyz" const wchar_t* wp = TO_LSTR(ABC) TO_LSTR(XYZ); // wp is L"abc" L"xyz"; } |
ソース
https://github.com/ambiesoft/blogprogs/tree/master/5910/literalmacro
コンパイルに/Pオプションを付けるとマクロの展開した時点のソースを拡張子.iをつけて出力してくれる。