‘#’
宏定义中一个#表示右侧的符号转化为字符串,比如:
#define STR(x) #x
QString s = STR(3)
编译ok,s值为"3"。
之前在看QT源码时,发现了下面的宏定义:
# define QLOCATION "\0" __FILE__ ":" QT_STRINGIFY(__LINE__)
#define QT_STRINGIFY2(x) #x
#define QT_STRINGIFY(x) QT_STRINGIFY2(x)
第一行的好理解,就是把文件行号拼起来,后面两行看起来有点重复,中间多了一层转换,我就试了下两个宏有什么不同:
#define STR(x) #x
#define STR1(x) STR(x)
QString s = STR(3);
#define NUM 3
QString s1 = STR(NUM);
QString s2 = STR1(NUM);
qDebug() << s << s1 << s2;
输出结果:“3” “NUM” “3”
使用STR(NUM)
传入宏时结果为"NUM",说明NUM宏没有被展开,所以前面中间多了一层。
如果#右侧的符号本身就是字符串会怎么样呢,我们试试:
#define _STR(x) #x
#define STR(x) _STR(x)
#define TTT(x) _STR(abc x)
QString sp = TTT("123");
qDebug() << sp;
上面加了一个TTT宏,TTT("abc")
展开为_STR(abc "123")
,再展开得到#abc "123"
,实际的输出结果是"abc \"123\""
,而且中间的空格并没有中断#的处理(当时发现中间有空格,想着在#define _STR(x) #x
的x加个括号,发现报错不让加,原来有空格也没问题)。
‘##’
##表示将左右的符号拼接在一起。例如拼接变量名:
#define INT(name) INT_##name
int INT_A = 13;
int INT_B = 10;
int a = INT(A); // INT(A)展开为INT_##A,通过##连接得到INT_A
int b = INT(B);
qDebug() << a << b;
输出13 10。
同样,##的参数如果是宏的话也不会展开,需要写中间宏来处理
#define _INT2(name) INT_##name
#define INT2(name) _INT2(name)
#define INT(name) INT_##name
#define NAME A
int INT_A = 13;
int INT_B = 10;
int a = INT(NAME); // 编译失败,提示INT_NAME不存在
int aa = INT2(NAME); // 成功展开为INT_A
从上面可以看出,如果##的参数是宏的话,需要写一个中间层去处理
总结
- #表示右侧的符号转化为字符串
- ##只是简单的将左右两边的符号连接在一起。
- #和##的参数如果是宏,都需要写一个中间宏来扩展,否则参数宏不会展开