关于宏##的使用注意一点

系统 1591 0

在看《C语言高级编程》时,里面有个关于宏##的题目:

      
        1.已知#define A “menu”

#define B “osd”,

若请使用宏A,B表示出字符串”menuosd”



答案:1 答案1:#define C A B

答案2:#define _C_(a,b) a##b

#define C(a,b) _C_(a,b)
      
    

 

然后我实际动手测试了一下,先来第一种:

      #include <stdio.h>


      
        #define
      
       A "menu"


      
        #define
      
       B "osd"


      
        #define
      
       STR A B




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

{


      
      
        char
      
       *p =
      
         STR;


      
      
        return
      
      
        0
      
      
        ;

}
      
    
      gcc -E hell.c -
      
        o hello.i

cat hello.i
      
    

结果:

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

{





char *p = "menu" "osd";





return 0;

}
      
    

 

第一个答案其实预编译后给出的结果是不完全符合要求的。

然后是第二种:

      #include <stdio.h>


      
        #define
      
       A "menu"


      
        #define
      
       B "osd"




      
        #define
      
       _C_(a,b) a##b


      
        #define
      
       C(a,b) _C_(a,b)




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

{


      
      
        char
      
       *p =
      
         C(A,B);

printf(
      
      
        "
      
      
        %s\n
      
      
        "
      
      
        , p);


      
      
        return
      
      
        0
      
      
        ;

}
      
    

 

首先,为什么要定义两个宏,一个不能解决问题吗?是的,不能。为什么?看这个链接:[ 短小精悍的宏 ](http://www.cnblogs.com/wb-DarkHorse/archive/2013/04/27/3046749.html)
然后再次按照上边的命令进行预编译,但是给出了错误信息: pasting "menu" and "osd" does not give a valid preprocessing token gcc
这就奇怪了。然后google了一下,发现了相同的问题:
[ 问题 ](http://stackoverflow.com/questions/4667779/preprocessor-macro-gcc-pasting-x-and-x-does-not-give-a-valid-preprocessing-toke)

并且里面说了,这种情况在VS里面不会报错,可以直接工作。so?

      #include <stdio.h>


      
        #define
      
       A "menu"


      
        #define
      
       B "osd"




      
        #define
      
       _C_(a,b) a##b


      
        #define
      
       C(a,b) _C_(a,b)




      
        int
      
       _tmain(
      
        int
      
       argc, _TCHAR*
      
         argv[])

{


      
      
        char
      
       *p = C(A,B);
      
        //
      
      
        STR;
      
      

printf(
      
        "
      
      
        %s\n
      
      
        "
      
      
        , p);


      
      
        return
      
      
        0
      
      
        ;

}
      
    

 

果然给出了结果: menuosd

为什么gcc和VS会对这个问题给出差异的结果呢?看这个问题:
[ that's why ](http://stackoverflow.com/questions/1206624/differences-in-macro-concatenation-operator-between-visual-c-and-gcc?rq=1)

根据C标准,用##操作后的结果必须是一个已经预定义过的符号。否则是未定义的。所以gcc和vs对于这个未定义行为表示了不同的看法,前者是给出错误,后者一笑而过。那什么是已经预定过的符号呢? 它包含了这些:头文件名, 等式, 预处理数字, 字符常数, 字符串值, 标点符号, 单个非空字符

在我们的例子中,_C_(a,b)用##连接后,应该是产生menuosd,但是这是一个未预定义的字符串,所以产生了一个未定义的行为。我们再看一个例子:

      
        #define
      
       A 2


      
        #define
      
       _CONS(a,b) (a##e##b)


      
        #define
      
       CONS(a,b) _CONS(a,b)




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

{

printf(
      
      
        "
      
      
        %f\n
      
      
        "
      
      
        , CONS(A, A));


      
      
        return
      
      
        0
      
      
        ;

}
      
    

 

这个时候gcc不会给出错误提示了。结果:200.0000
为什么这个时候不给出错误提示呢?我的理解是,CONS(A, A)替换后成为2e2,而这时一个常量,符合C标准。

ok,给出一个链接,详细的解释了gcc中##的用法:
[ gcc concatenation ](http://gcc.gnu.org/onlinedocs/gcc-4.3.3/cpp/Concatenation.html#Concatenation)

 

 

关于宏##的使用注意一点


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论