C语言中#和##的用法

来源:互联网 发布:网络投影机 编辑:程序博客网 时间:2024/05/16 10:21

转自:http://topic.csdn.net/u/20070727/14/c77ae5f0-050f-47be-8132-7dc305eead98.html


一、一般用法   
我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起.   
用法:   
#i   nclude <cstdio>   
#i   nclude <climits>   
using   namespace   std;   

#define   STR(s)           #s   
#define   CONS(a,b)     int(a##e##b)   

int   main()   
{   
        printf(STR(vck));                       //   输出字符串 "vck "   
        printf( "%d\n ",   CONS(2,3));     //   2e3   输出:2000   
        return   0;   
}   

二、当宏参数是另一个宏的时候   
需要注意的是凡宏定义里有用 '# '或 '## '的地方宏参数是不会再展开.   

1,   非 '# '和 '## '的情况   
#define   TOW             (2)   
#define   MUL(a,b)   (a*b)   

printf( "%d*%d=%d\n ",   TOW,   TOW,   MUL(TOW,TOW));   
这行的宏会被展开为:   
printf( "%d*%d=%d\n ",   (2),   (2),   ((2)*(2)));   
MUL里的参数TOW会被展开为(2).   

2,   当有 '# '或 '## '的时候   
#define   A                     (2)   
#define   STR(s)           #s   
#define   CONS(a,b)     int(a##e##b)   

printf( "int   max:   %s\n ",     STR(INT_MAX));         //   INT_MAX   #i   nclude <climits>   
这行会被展开为:   
printf( "int   max:   %s\n ",   "INT_MAX ");   

printf( "%s\n ",   CONS(A,   A));                               //   compile   error     
这一行则是:   
printf( "%s\n ",   int(AeA));   

INT_MAX和A都不会再被展开,   然而解决这个问题的方法很简单.   加多一层中间转换宏.   
加这层宏的用意是把所有宏的参数在这层里全部展开,   那么在转换宏里的那一个宏(_STR)就能得到正确的宏参数.   

#define   A                       (2)   
#define   _STR(s)           #s   
#define   STR(s)             _STR(s)                     //   转换宏   
#define   _CONS(a,b)     int(a##e##b)   
#define   CONS(a,b)       _CONS(a,b)               //   转换宏   

printf( "int   max:   %s\n ",   STR(INT_MAX));                     //   INT_MAX,int型的最大值,为一个变量   #i   nclude <climits>   
输出为:   int   max:   0x7fffffff   
STR(INT_MAX)   -->     _STR(0x7fffffff)   然后再转换成字符串;   

printf( "%d\n ",   CONS(A,   A));   
输出为:200   
CONS(A,   A)     -->     _CONS((2),   (2))     -->   int((2)e(2))   

三、 '# '和 '## '的一些应用特例   
1、合并匿名变量名   
#define     ___ANONYMOUS1(type,   var,   line)     type     var##line   
#define     __ANONYMOUS0(type,   line)     ___ANONYMOUS1(type,   _anonymous,   line)   
#define     ANONYMOUS(type)     __ANONYMOUS0(type,   __LINE__)   
例:ANONYMOUS(static   int);     即:   static   int   _anonymous70;     70表示该行行号;   
第一层:ANONYMOUS(static   int);     -->     __ANONYMOUS0(static   int,   __LINE__);   
第二层:                                                 -->     ___ANONYMOUS1(static   int,   _anonymous,   70);   
第三层:                                                 -->     static   int     _anonymous70;   
即每次只能解开当前层的宏,所以__LINE__在第二层才能被解开;   

2、填充结构   
#define     FILL(a)       {a,   #a}   

enum   IDD{OPEN,   CLOSE};   
typedef   struct   MSG{   
    IDD   id;   
    const   char   *   msg;   
}MSG;   

MSG   _msg[]   =   {FILL(OPEN),   FILL(CLOSE)};   
相当于:   
MSG   _msg[]   =   {{OPEN,   "OPEN "},   
                            {CLOSE,   "CLOSE "}};   

3、记录文件名   
#define     _GET_FILE_NAME(f)       #f   
#define     GET_FILE_NAME(f)         _GET_FILE_NAME(f)   
static   char     FILE_NAME[]   =   GET_FILE_NAME(__FILE__);   

4、得到一个数值类型所对应的字符串缓冲大小   
#define     _TYPE_BUF_SIZE(type)     sizeof   #type   
#define     TYPE_BUF_SIZE(type)       _TYPE_BUF_SIZE(type)   
char     buf[TYPE_BUF_SIZE(INT_MAX)];   
          -->     char     buf[_TYPE_BUF_SIZE(0x7fffffff)];   
          -->     char     buf[sizeof   "0x7fffffff "];   
这里相当于:   
char     buf[11];

原创粉丝点击