您现在的位置是:首页 >技术交流 >c/c++ 宏定义里的#和##网站首页技术交流

c/c++ 宏定义里的#和##

爱跑步的码农 2024-06-17 10:31:53
简介c/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
", ret, #func);} 
} while (0);

int func_for_test(int value);
int main()
{
	int val = 200;
	printf("%s
", 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
", NAME_JOIN(func_for_test, _1));
	return 0;
}

int func_for_test_1()
{
	return 10;
}

假如我改成 printf("%p ", NAME_JOIN(func_for_test1, _1)); 在编译的时候会出现错误:

因为 NAME_JOIN(func_for_test1, _1) 只是简单的把两个短语连接为一个短语,而连接后的这个短语是否有效那就要做语法检测了,如上面执行的结果为:打印函数的地址

那如果改成这样:printf("ret = %d ", 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
", 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
", NAME_JOIN(func_for_test, NUMBER_1)());
        return 0;
}

int func_for_test_1()
{
        return 10;
}

这样就能正确展开,编译成功。

 

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。