宏 # ##符号 的用法

#把宏参数变为一个字符串,而##把两个宏参数贴合在一起。

一、一般用法:

#include <stdio.h>
#define STR(s)    #s
#define CONSS(a,b) (int)a##e##b

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

#注意:

a。忽略传入参数名前面和后面的空格。

   如:str=example1(   abc ); 将会被扩展成 str="abc";

b.当传入参数名间存在空格时,编译器将会自动连接各个子字符串,用每个子字符串中只以一个空格连接,忽略其中多余一个的空格。

 

##注意

1.当用##连接形参时,##前后的空格可有可无。

如:#define exampleNum(n) num ## n 相当于 #define exampleNum(n) num##n

2.连接后的实际参数名,必须为实际存在的参数名或是编译器已知的宏定义

 

二、宏参数是另一个宏

1、非'#'和'##'的情况:

#include <stdio.h>
#define TOW      (2)
#define MUL(a,b) (a*b)
int main()
{
 printf("%d*%d=%d/n", TOW, TOW, MUL(TOW,TOW));
    return 0;
}

展开的结果是:

printf("%d*%d=%d/n", (2), (2), ((2)*(2)));

所以:没有使用#符号时,会递归的全部展开。

2、 当有'#'或'##'的时候
需要注意的是凡宏定义里有用'#'或'##'的地方宏参数是不会再展开。如下:

#include <stdio.h>
#define INT_MAX  0x7fffffff
#define STR(s)     #s
int main()
{
    printf("int max: %s/n",  STR(INT_MAX));     //输出:int max: INT_MAX
    printf("int max: %d/n",  INT_MAX);              //输出:int max: 2147483647
    return 0;
}

如果定义:

#include <stdio.h>
#define A (2)
#define CONSS(a,b)  (int)a##e##b
int main()
{
    printf("%d/n",  CONSS(A,A));    
    return 0;
}

则编译时会报错,因为无法将A展开,所以(int)(2)e(2)会出错。

解决办法:加多一层中间转换宏。加这层宏的用意是把所有宏的参数在这层里全部展开, 那么在转换宏里的那一个宏就能得到正确的宏参数。

#include <stdio.h>
#define A           2
#define _STR(s)     #s
#define STR(s)      _STR(s)                     // 转换宏
#define _CONSS(a,b)  (int)a##e##b
#define CONSS(a,b)   _CONSS(a,b)       // 转换宏

int main()
{
    printf("%d/n",  CONSS(A,A));    
    printf("%d/n",  STR(A));    
    return 0;
}

 

三、'#'和'##'的一些应用特例

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、得到一个数值类型所对应的字符串缓冲大小

#include <stdio.h>
#define INT_MAX 0x7fffffff
#define  _TYPE_BUF_SIZE(type)    sizeof #type
#define  TYPE_BUF_SIZE(type)   _TYPE_BUF_SIZE(type)

int main()
{
    printf("%d/n",  TYPE_BUF_SIZE(INT_MAX));   //11
    return 0;
}

相当于:

TYPE_BUF_SIZE(INT_MAX)—>_TYPE_BUF_SIZE(0x7fffffff)—>sizeof "0x7fffffff";

 

 

3、@# (charizing)字符化操作符。

只能用于有传入参数的宏定义中,且必须置于宏定义体中的参数名前。作用是将传的单字符参数名转换成字符,以一对单引用括起来。

#define makechar(x)  #@x

a = makechar(b);

展开后变成了:

a= 'b';

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值