宏中 # 和 ## 的用法

455 阅读2分钟

参考 blog.csdn.net/Apollon_krj…

一般用法

# 把宏参数变为一个字符串,用 ## 把两个宏参数贴合在一起,例如:

#include <cstdio>
#include <climits>
using namespace std;

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

int main()
{
    printf(STR(vck)  "\n");		// vck

    printf("%d\n", CONS(2, 3));		// 2e3, 2000
    return 0;
}

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

凡宏定义里有用#或##的地方宏参数是不会再展开

  1. 没有 # 和 ## 的情况、
#include <cstdio>

#define TOW		(2)
#define MUL(a,b)	(a*b)

int main()
{
    printf("%d*%d=%d\n", TOW, TOW, MUL(TOW, TOW));
}

这里被展开为

printf("%d*%d=%d\n", (2), (2), ((2)*(2)));
  1. 有 # 或 ## 的时候
#include <cstdio>
#define	A           2
#define	STR(s)	    #s
#define	CONS(a,b)   int(a##e##b)

int main()
{
    printf("int max: %s\n", STR(INT_MAX));			//  INT_MAX
    printf("%s\n", CONS(A, A));					//  AeA
}

解决这个问题的办法,加多一层中间转换宏。

#include <cstdio>
#include <climits>

#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)

int main()
{
    printf("int max: %s\n", STR(INT_MAX));
    printf("%d\n", CONS(A, A));
}
  1. 应用实例
  • 合并匿名变量名
#include <cstdio>

#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;

ANONYMOUS(static int); -> _ANONYMOUS0(static int, __LINE__)

__ANONYMOUS1(static int, _anonymous, 70)

static int _anonymous70;

  • 填充结构
#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"}
};
*/
  • 记录文件名
#define _GET_FILE_NAME(f)  #f
#define GET_FILE_NAME(f)   _GET_FILE_NAME(f)

static char FILE_NAME[] = GET_FILE_NAME(__FILE__);
  • 得到一个数值类型所对应的字符串缓冲大小
#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[sizeof "0x7fffffff"]; char buf[11];

__VA_ARGS__ 与 ##__VA_ARGS__

__VA_ARGS__ 是一个可变参数的宏,实现思想就是宏定义中参数列表的最后一个参数为省略号。##__VA_ARGS__ 宏,在 __VA_ARGS__ 前面加上 ## 的作用在于,当可变参数的个数为 0 时,这里的 ## 起到把前面多余的逗号去掉的作用,否则会编译出错。