Chinaunix首页 | 论坛 | 博客
  • 博客访问: 43136
  • 博文数量: 16
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 32
  • 用 户 组: 普通用户
  • 注册时间: 2013-10-28 20:43
个人简介

天道酬勤

文章分类

全部博文(16)

文章存档

2016年(1)

2015年(12)

2014年(2)

2013年(1)

我的朋友

分类: C/C++

2015-07-18 12:59:55

一、一般用法 
我们使用#把宏参数变为一个字符串,##把两个宏参数贴合在一起
用法

点击(此处)折叠或打开


  1. #include <stdio.h>

  2. #define STR(s) #s
  3. #define CONS_1(a,b) (a##e##b)


  4. void other_test()
  5. {
  6.     //printf("%d\n", 4e3);     //error,输出0,格式不匹配
  7.     printf("%g\n", 4e3);       //4000
  8.     printf("%d\n", (int)4e3);  //4000
  9. }

  10. /*
  11. ** "#","##" test
  12. */
  13. void macro_parameter_test_1(void)
  14. {    
  15.     printf("%s\n", STR(test));        //printf("%s\n", "test");
  16.     printf("%d\n",(int)CONS_1(2,3)) //2000
  17. }


  18. int main()
  19. {
  20.     //other_test();
  21.     macro_parameter_test_1();

  22.     return 0;
  23. }

二、当宏参数是另一个宏的时候 

需要注意的是凡宏定义里有用'#''##'的地方宏参数是不会再展开,但宏定义中没有使用“#”和“##”的地方宏可以嵌套

1, '#''##'的情况(不含#,##符号的嵌套) 

点击(此处)折叠或打开

  1. #include <stdio.h>
  2.  
  3. #define TOW (2)
  4. #define MUL(a,b) (a*b)

  5. int main()
  6. {
  7.     printf("%d*%d=%d\n", TOW, TOW, MUL(TOW,TOW)); 
  8.     /*
  9.     ** 宏展开:printf("%d*%d=%d\n", (2), (2), ((2)*(2)));
  10.     ** MUL里的参数TOW也会被展开为(2).
  11.     */
  12.     return 0
  13. }

2, 
当有'#''##'的时候(含有#,##符号的宏嵌套)

点击(此处)折叠或打开


  1. #include <stdio.h>
  2. #include <limits.h>

  3. #define A 2
  4. #define STR(s) #s
  5. #define CONS(a,b) (a##e##b)

  6. int main(void)
  7. {
  8.     printf("%x\n", INT_MAX);      //0x7fffffff
  9.     //printf("%x\n", INT_MIN);    //0x80000000

  10.     printf("%s\n", STR(INT_MAX)); //printf("%s\n", "INT_MAX"); INI_MAX没有被替换
  11.     printf("%s\n", STR(A));       //printf("%s\n","A"); A没有被替换
  12.     
  13.     printf("%g\n", CONS(A,A));    //error, A没有被替换
  14.     return 0;    
  15. }

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

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <limits.h>

  3. #define A 2
  4. #define STR(s) #s
  5. #define CONS(a,b) (a##e##b)

  6. #define _STR(s) STR(s)        //转换宏
  7. #define _CONS(a,b) CONS(a,b)  //转换宏

  8. int main(void)
  9. {
  10.     printf("%x\n", INT_MAX);        //0x7fffffff
  11.     //printf("%x\n", INT_MIN);      //0x80000000

  12.     printf("%s\n", _STR(INT_MAX));  //printf("%s\n", "2147483647")INI_MAX被替换,但是是以10进制格式输出 
  13.     printf("%s\n", _STR(A));        //printf("%s\n", "2");
  14.     
  15.     printf("%g\n", _CONS(A,A));     //200
  16.     return 0;    
  17. }

  18. /* 
  19. ** _STR(INT_MAX) --> STR(2147483647) -->转换为字符串
  20. ** _STR(A) --> STR(2)  --> "2"
  21. ** _CONS(A,A) --> CONS(2,2) --> 2e2
  22. */


    延伸:当含有#,##符号时,宏参数不能嵌套,在#,##两边含有宏时也不能嵌套

点击(此处)折叠或打开

  1. #include <stdio.h>

  2. #define X e
  3. #define CONS(a,b) (a##X##b)

  4. int main()
  5. {
  6.     printf("%f\n", CONSS(2,3));  //error, X不被替换
  7. }

三、
'#''##'的一些应用特例 
1、合并匿名变量名 

点击(此处)折叠或打开


  1. #define ___ANONYMOUS1(type, var, line) type var##line
  2. #define __ANONYMOUS0(type, line) ___ANONYMOUS1(type, _anonymous, line)
  3. #define ANONYMOUS(type) __ANONYMOUS0(type, __LINE__)

  4. /*
  5. ** 例:ANONYMOUS(static int);: static int _anonymous70; 70表示该行行号;
  6. ** 第一层:ANONYMOUS(static int); --> __ANONYMOUS0(static int, __LINE__);
  7. ** 第二层: --> ___ANONYMOUS1(static int, _anonymous, 70);
  8. ** 第三层: --> static int _anonymous70;
  9. ** 即每次只能解开当前层的宏,所以__LINE__在第二层才能被解开;
  10. */
2、填充结构 

点击(此处)折叠或打开

  1. #define FILL(a) {a, #a}

  2. enum IDD{OPEN, CLOSE};
  3. typedef struct MSG{
  4.     IDD id;
  5.     const char * msg;
  6. }MSG;

  7. MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};
  8. /*
  9. ** MSG _msg[] = {{OPEN, "OPEN"},
  10. ** {CLOSE, "CLOSE"}};
  11. */

3、记录文件名 

点击(此处)折叠或打开

  1. #define _GET_FILE_NAME(f) #f
  2. #define GET_FILE_NAME(f) _GET_FILE_NAME(f)
  3.  
  4. static char FILE_NAME[] = GET_FILE_NAME(__FILE__);

小例子:

点击(此处)折叠或打开

  1. #include<stdio.h>
  2. #include<string.h>

  3. #define STRCPY(a,b) strcpy(a##_p,#b) //把第一个参数后边加上字符_p,把第二个参数变成字符串

  4. int main()
  5. {
  6.     char var1_p[20];
  7.     char var2_p[30];
  8.     strcpy(var1_p,"aaaa");
  9.     strcpy(var2_p,"bbbb");
  10.     
  11.     STRCPY(var1,var2); //等于strcpy(var1_p,"var2");
  12.     STRCPY(var2,var1); //等于strcpy(var2_p,"var1");
  13.     
  14.     printf("%s\n",var1_p);
  15.     printf("%s\n",var2_p);
  16.     return 0;
  17. }

转自:http://www.cnblogs.com/hnrainll/archive/2012/08/15/2640558.html
阅读(935) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~