C++宏定义中#和##的用法
程序员文章站
2024-03-22 10:20:23
...
前段时间很到了宏定义中的新知识:#与##,感觉打开了新天地的大门。
首先来介绍一下这两种功能:
#
#的用法是负责将其后面的东西转化为字符串,比如:
#define TO_STRING(str) #str
int main(){
cout << TO_STRING(this is a string) << endl;
return 0;
}
这段代码中,TO_STRING宏就会将括号中的内容转化为字符串,生成"this is a string",然后由cout输出。
##
##是连接符,将前后两个东西连接成一个词。比如:
#define IntVar(i) int_##i
int main(){
int int_1 = 1, int_2 = 2;
cout << IntVar(1) << ", " << IntVar(2) << endl;
return 0;
}
这段代码中IntVar(1)就会将前面的int_与参数1连接起来,成为int_1,然后由cout输出int_1变量对应的值1。对于IntVar(2)同理。
最开始我一看,emmmmmm,高级啊!可以生成新的词汇!因为我最开始想做的是,如果有很多int变量,他们基本模式都一样,那我是不是可以用一个for循环来直接生成?比如:
#define create_int(i) int int_##i = i
#define print_int(i) cout << int_##i << endl
int main(){
for(int i = 1; i <= 3; ++i) create_int(i);
for(int i = 1; i <= 3; ++i) print_int(i);
}
这样。当然,我很快发现我想多了。我犯了一个很低级的错误。宏定义是在预编译的时候就进行了展开,i的值则是在运行时才确定下来的,想想也应该知道不可能达到我预想中的效果。这样做只会生成int_i变量,而不是int_1、int_2之类的。
那么##的正确打开方式是什么呢?其实它做的只是帮我们省去不变的部分,可变的部分仍然需要我们自己去完成。对于上面这个小小的示例用处可能不太明显,我们换一个:
#define TEST_CASE_1 "This is a super super super super long string for test to process"
#define TEST_CASE_2 "This is another super super super super long string for test to process"
#define TEST_CASE_3 "This is again another super super super super long string for test to process"
#define process_data(i) \
string temp = TEST_CASE_##i;\
do_something
int main(){
process_data(1);
process_data(2);
process_data(3);
}
比如说如上代码,do_something可能有很多行,而你重复的部分又难以做成循环,因为变量由于某种原因难以做成数组。这个时候用到##就会很方便啦~
另外,##还可以用来省略前缀。比如:
#define func(ptr, type) _func(ptr, T_##type)
enum TYPE{
T_INT,
T_FLOAT,
T_CHAR,
}
void _func(void* ptr, TYPE type){
switch(type){
case T_INT:
cout << *((int*)ptr) << endl; break;
case T_FLOAT:
cout << *((float*)ptr) << endl; break;
case T_CHAR:
cout << *((char*)ptr) << endl; break;
default:
break;
}
}
int main(){
int x = 1, *ptr = &x;
func(ptr, INT);
}
这样就可以省去前缀,看起来更方便。
当然还有更多的用法,我就不一一列举啦。
上一篇: Greenplum操作