先来段程序:

  1. #include <stdio.h>

  2. #define f(a,b) a##b

  3. #define g(a)   #a

  4. #define h(a)   g(a)

  5. #define p(a)   #@a

  6. int main(int argc, char* argv[])

  7. {

  8.    printf("%s\n", g(f(1,2)));

  9.    printf("%s\n", h(f(1,2)));

  10.    printf("%c, %d\n", p(1), p(1));

  11. return 0;

  12. }

输出结果

看上去有点奇怪。

##是连接操作符(我也不知道中文是啥,google到的是token-pasting operator),可以将操作符两端的标识符级联起来。

#是字符串化操作符(stringizing operator),可以将操作符后的标识符转化成字符串。

#@是字符化操作符(charizing),可以将操作符后的数据转化成字符。

来分析程序。

  1. printf("%s\n", g(f(1,2)));

g(f(1,2)),即#f(1,2),被转化成了字符串,于是g(f(1,2))就变成了"f(1,2)"。

  1. printf("%s\n", h(f(1,2)));  

h(f(1,2)),这里需要注意一下,#跟##不一样,如果宏定义的替换部分恰好跟其他的宏定义名字一样的话,会进行展开,即调用h(a)会先对g(a)进行展开。详见http://c-faq.com/ansi/stringize.html。如此一来,h(f(1,2))会先对f(1,2)进行运算,变成12,再运行h(12),变成"12"。

  1. printf("%c, %d\n", p(1), p(1));  

p(1),1被转化成字符,为了验证,输出它的ASCII码。

#,##, #@都仅适用于宏定义,在程序中无法单独使用。

参考:http://msdn.microsoft.com/en-us/library/teas0593%28v=vs.80%29.aspx