浅析C++宏定义里#和##的使用
作者:爱跑步的码农
工作中如果是c开发的话,经常会用到宏定义,而宏定义中的#和##也会时不时遇到,今天分享这两个符号的作用。
1,# -- 转换成字符串
直接看例子:
#include <stdio.h> #include <stdlib.h> #define VAL2STR(VAL) (#VAL) #define fun_call_rt(func) \ do \ { \ int ret = func; \ if(ret){printf("%d = %s\n", ret, #func);} \ } while (0); int func_for_test(int value); int main() { int val = 200; printf("%s\n", VAL2STR(200)); fun_call_rt(func_for_test(10)); return 0; } int func_for_test(int value) { if(value == 100) { return 0; } else { return -1; } }
我们可以直接用gcc -E 预编译看看宏展开后是什么样的?如用命令 gcc -E test_#.c -o preprocess_test 编译后,我们看最后的代码:
其中的 VAL2STR(200) 被替换成了 ("200"),fun_call_rt(func) 中的 #func 被替换成了 "func_for_test(10)",即都被替换成了字符串,在c语言中应该称为字符数组类型。
在一些公司中类似 fun_call_rt(func) 宏几乎处处可见,在每个函数调用的地方都是这个宏括起来,一旦有错误发生,打印输出一目了然。
2, ## -- 连接两个语句为一个语句
这里所说的语句,可以是函数名,类型名,变量名,但都需要有实际意义,否则就会编译不过,看代码:
#include <stdio.h> #include <stdlib.h> #define NAME_JOIN(x,y) x##y int func_for_test_1(); int main() { printf("%p\n", NAME_JOIN(func_for_test, _1)); return 0; } int func_for_test_1() { return 10; }
假如我改成 printf("%p\n", NAME_JOIN(func_for_test1, _1)); 在编译的时候会出现错误:
因为 NAME_JOIN(func_for_test1, _1) 只是简单的把两个短语连接为一个短语,而连接后的这个短语是否有效那就要做语法检测了,如上面执行的结果为:打印函数的地址
那如果改成这样:printf("ret = %d\n", NAME_JOIN(func_for_test, _1)()); 就是一个函数调用了,其结果就是:
而有一种情况这个 ## 可能不会是你想要的结果,那就是宏定义里又包含宏定义,如:
#include <stdio.h> #include <stdlib.h> #define NUMBER_1 _1 //#define NAME_JOIN(x,y) NAME_JOIN2(x,y) #define NAME_JOIN(x,y) x##y int func_for_test(int value); int func_for_test_1(); int main() { printf("ret = %d\n", NAME_JOIN(func_for_test, NUMBER_1)()); return 0; } int func_for_test_1() { return 10; }
NAME_JOIN(func_for_test, NUMBER_1) 宏定义里又包含了宏 NUMBER_1,这样编译会出现什么问题呢?
可以看到 NUMBER_1 没有被展开,我们想要的是它被展开为 -1,即 func_for_test_1。处理办法就是再多加一个宏定义,如:
#include <stdio.h> #include <stdlib.h> #define NUMBER_1 _1 #define NAME_JOIN(x,y) NAME_JOIN2(x,y) #define NAME_JOIN2(x,y) x##y int func_for_test(int value); int func_for_test_1(); int main() { printf("ret = %d\n", NAME_JOIN(func_for_test, NUMBER_1)()); return 0; } int func_for_test_1() { return 10; }
这样就能正确展开,编译成功。
以上就是浅析C++宏定义里#和##的使用的详细内容,更多关于C++宏定义的资料请关注脚本之家其它相关文章!