#define A hoge
#define B piyo
マクロで書かれた2つの文字A,Bを結合してprintfで表示したいのですが、
次のように関数マクロの引き数に関数マクロをつかっても、マクロが変換されないで
そのままになってしまいます。
#define STRCAT(a,b) a ## b
#define TOSTR(n) #n
int main(int argc,char* argv[]){
printf(TOSTR(STRCAT(hoge,piyo)));
}
実行結果。
C:\>STRCAT(hoge,piyo)
もしかして関数マクロの中にマクロはだめなのでしょうか?
ご存知のかたがいらっしゃいましたらどうかよろしくお願いします。
#って何の演算子?
TOSTRが先に実行されてしまうってことか。
このようにするとどうなりますか?
#define STRCAT(a,b) a ## b
#define TOSTR2(n) #n
#define TOSTR(n) TOSTR2(n)
> #って何の演算子?
プリプロセッサの引数で、値ではなく引数の文字列を取るためのものです。
ちなみに、## ってのは、文字連結用。
>みな様
お返事ありがとうございます。
>超初心者様
>TOSTRが先に実行されてしまうってことか。
そうみたいなんです。
>michi様
いわれたとおり実行してみました。
#define STRCAT(a,b) a ## b
#define TOSTR2(n) #n
#define TOSTR(n) TOSTR2(n)
int main(int argc,char* argv[]){
printf(TOSTR(STRCAT(hoge,piyo)));
}
実行結果。
C:\>hogepiyo
なんでこれでうまくいくの??????
#define A hoge
#define B piyo
#define STRCAT2(a,b) a ## b
#define STRCAT(a,b) STRCAT2(a,b)
#define TOSTR2(n) #n
#define TOSTR(n) TOSTR2(n)
int main(int argc,char* argv[]){
printf(TOSTR(STRCAT(A,B)));
}
実行結果。
C:\>hogepiyo
上記のようにすることで目的のマクロができました。
でも、どうしてこれでうまくいくのかわかりません。
たまたまコンパイラがこうゆう仕様だからでしょうか?
鼻から悪魔なことになってないでしょうか?
すみません書きわすれましたがコンパイラはMINGW-JP(MIGWの日本語版)のgccです。
(あとmain関数の最後にreturn;を書くのもわすれてました。)
完全に処理系依存で、私も詳しく分かりません。
とりあえず、
TOSTR(STRCAT(hoge,piyo)) -> "STRCAT(hoge,piyo)"
の変換をさけるために、余計にマクロ(TOSTR2,STRCAT2)を挟んであげればいいようですね。
ちなみに私は
TOSTR(__LINE__) -> "__LINE__"
にならないようTOSTR2を使ってます。
> 上記のようにすることで目的のマクロができました。
> でも、どうしてこれでうまくいくのかわかりません。
> たまたまコンパイラがこうゆう仕様だからでしょうか?
標準仕様どおりでよいと思います。
JIS X 3010 6.10.3.1 実引数置換
| 実引数の中に含まれるすべてのマクロの展開後、置換要素並びの中の
| 仮引数を対応する実引数で置き換える。ただし、次の仮引数は除く。
| - #前処理字句又は##前処理字句が前にある仮引数
| - ##前処理字句が後に続く仮引数
>#define TOSTR2(n) #n
これは #n という使われ方をしているので、
実引数のマクロ展開は行われない。
> #define TOSTR(n) TOSTR2(n)
これは n という使われ方をしているので、
実引数のマクロ展開が行われる。
>michi 様、dairygoods様
レス大変ありがとうございます。
>実引数の中に含まれるすべてのマクロの展開後、置換要素並びの中の
>仮引数を対応する実引数で置き換える。
#define TOSTR(n) TOSTR2(n)
とはまずnをマクロ展開後、TOSTR2()の関数マクロが実行されるということ??
ということは・・・・・・・・・
TOSTR(STRCAT(A,B))
はまず実引数?のSTRCAT(A,B)がマクロ展開されるんだけど、さらにその実引数のA,Bが最初にマクロ展開されて、
TOSTR(STRCAT(hoge,piyo))になり、
TOSTR(STRCAT2(hoge,piyo))になり、
TOSTR(hogepiyo)になって
TOSTR2(hogepiyo)
最後に"hogepiyo"となるんですね!!!!
・・・あってますでしょうか?
単純に、
#define STRCAT(a,b) #a #b
だけでもいいとおもうのですが…
>jackdaw様
レスありがとうござます。下記のコードを実行してみました。
#define A hoge
#define B piyo
#define STRCAT(a,b) #a #b
int main(int argc,char* argv[]){
printf(STRCAT(A,B));
return 0;
}
実行結果は"AB"となり目的の機能をはたしてくれません。
#define STRCAT2(a,b) #a #b
#define STRCAT(a,b) STRCAT2(a,b)
とすれば実行結果は"hogepiyo"になりました。
ただどうして#a#bの間のスペースはなくなるんでしょうか?
>ただどうして#a#bの間のスペースはなくなるんでしょうか?
検索したらでてきました。
C 言語では、並んだ二つの文字列定数は一つの文字列定数に併合する決まりになっているんですね。ありがとうございました。
>みな様
"解決"です。
レス本当にありがとうございました。勉強になりました。
ツイート | ![]() |