一般用法
# 把宏参数变为一个字符串,用 ## 把两个宏参数贴合在一起,例如:
#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;
}
当宏参数是另一个宏的时候
凡宏定义里有用#或##的地方宏参数是不会再展开
- 没有 # 和 ## 的情况、
#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)));
- 有 # 或 ## 的时候
#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));
}
- 应用实例
- 合并匿名变量名
#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 时,这里的 ## 起到把前面多余的逗号去掉的作用,否则会编译出错。