c语言里的宏(翻译) 5

原文在这里

字符化

有的时候,你也会想把一个宏参数直接转化成一个字符常量。你想要在某个字符串中插入宏参数,期待它会简单的被替换成字符常量,想法不错,但不可能。不过你可以用"#"预处理操作符。当一个宏参数前置"#"时,预处理器就会把宏参数符号替换成跟宏参数符号相同的字符常量。与常规参数替换不同的是,该类转化不叫宏展开,而叫"字符化"。

把一个宏参数混在字符串内部,然后字符化它,这种操作是不可能成功的。相反,你应该写一系列独立的字符常量,并把宏参数夹在各字符常量之间。预处理器会把宏参数字符化,然后c编译器会把所有独立的字符串合成一条长字符串。

下面是一个使用了字符化的宏的例子

     #define WARN_IF(EXP) \
     do { if (EXP) \
             fprintf (stderr, "Warning: " #EXP "\n"); } \
     while (0)
     WARN_IF (x == 0);
          ==> do { if (x == 0)
                fprintf (stderr, "Warning: " "x == 0" "\n"); } while (0);
参数EXP一次在if语句里使用,还有一次在fprintf函数里被字符化。如果x也是一个宏,在if语句里会继续展开,但是在字符化时不会。
do while(0)循环是一个小伎俩,使得WARN_IF(arg);这种写法成为可能,否则的话宏内容里的if语句会把正常的c语言流程搞糟。参看大括号对齐
c里面的字符化可不是在参数两边加引号这么简单,它还会把各类特殊字符转义,以便得到一个合法的c字符串。所以,字符串p = “foo\n”当成参数传入宏,字符化后的结果是"p = \"foo\\n\";"。但是本来就是特殊字符的那些还是保留原样,比如字符'\n’字符化后是"\n"。
所有前置和后置的空格都会被忽略。所有在中间的空格都会被转化成一个空格。注释早在执行字符化之前一百万年就已经被预处理器干掉了,所以字符化结果里绝不会有注释。
想把一个宏参数转成字符常量(而不是字符串常量),是没可能做到的。
如果你想看一个宏展开后是什么样子,可以用两级宏:
     #define xstr(s) str(s)
     #define str(s) #s
     #define foo 4
     str (foo)
          ==> "foo"
     xstr (foo)
          ==> xstr (4)
          ==> str (4)
          ==> "4"
posted @ 2008-10-25 00:04  gussing  阅读(920)  评论(0编辑  收藏  举报