トークン連結子

マクロ展開を極めるような事はした事が無かったので、この辺りはちゃんとした知識は持っていなかったんだけど、なんか #を付けると文字列に展開されて ##だとトークンのまま連結して、、、とか位は覚えてた。で、構造体のメンバーを調査するのに、

#define P(member) printf(#member ":\t%d ,  ", (vmStat. ##member))

のような事をしてハマる。

hugemem.m:40:1: error: pasting "." and "free_count" does not give a valid preprocessing token
hugemem.m:41:1: error: pasting "." and "active_count" does not give a valid preprocessing token
hugemem.m:42:1: error: pasting "." and "inactive_count" does not give a valid preprocessing token
hugemem.m:44:1: error: pasting "." and "wire_count" does not give a valid preprocessing token
hugemem.m:45:1: error: pasting "." and "zero_fill_count" does not give a valid preprocessing token
hugemem.m:46:1: error: pasting "." and "reactivations" does not give a valid preprocessing token
    :

のわー、なんかいっぱいおこられた。-Eで展開してみると問題なさそうでコンパイルもちゃんと通るから単純にrestrictiveなだけだとは思うんだけど、いったい何が起きてるんだろう? とか思ってぐぐってみると freetype-1.3とかでも昔問題があったらしい。 ##は「トークン」連結演算子なので連結結果は「1トークン」で無ければいけない、という制約が後から付いたんだそうな。だからさっきのはトークン連結なんぞせずに

#define P(member) printf(#member ":\t%d ,  ", (vmStat. member))

としたら普通にイケた。もちろんこれは vmStat.memberと展開されるんだけど、文法的にそれで問題ないので普通にメンバアクセスできる。当然これは . だけじゃなくすべての演算子で言える事で、というかちゃんと考えてみたら当たり前の事で、例によって自分のアホさ加減にちょっと落ち込む。
さらに、書いてて気がついたが、

#define P(member) printf(#member ":\t%d ,  ", (vmStat.member))

スペースなんぞ入れなくても分割できるよ! 本当にバカか僕は。
まあ、バカはバカなりに、誰かの役に立てれば良いのさ ...... TT