浅析C++宏定义里#和##的使用

 更新时间:2023年05月18日 09:20:00   作者:爱跑步的码农  
工作中如果是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++宏定义的资料请关注脚本之家其它相关文章!

相关文章

  • 解析C/C++指针、函数、结构体、共用体

    解析C/C++指针、函数、结构体、共用体

    这篇文章主要介绍了C/C++指针、函数、结构体、共用体的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-01-01
  • C语言实现简单酒店管理系统

    C语言实现简单酒店管理系统

    这篇文章主要为大家详细介绍了C语言实现简单酒店管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • 使用pthread库实现openssl多线程ssl服务端和客户端

    使用pthread库实现openssl多线程ssl服务端和客户端

    使用pthread库实现openssl多线程ssl服务端和客户端,大家参考使用吧
    2014-01-01
  • C语言字符串与字符数组面试题中最易错考点详解

    C语言字符串与字符数组面试题中最易错考点详解

    这篇文章主要介绍了C语言字符串与字符数组面试题中最易错考点,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-09-09
  • C++实现图书馆管理系统

    C++实现图书馆管理系统

    这篇文章主要为大家详细介绍了C++实现图书馆管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • C++类基本语法实例分析

    C++类基本语法实例分析

    这篇文章主要介绍了C++类基本语法实例分析,非常适合初学者学习借鉴,需要的朋友可以参考下
    2014-08-08
  • C/C++实现快速排序算法的两种方式实例

    C/C++实现快速排序算法的两种方式实例

    快速排序是一种采用分治思想,在实践中通常运行较快一种排序算法,这篇文章主要给大家介绍了关于C/C++实现快速排序的两种方式的相关资料,文中给出了详细的示例代码,需要的朋友可以参考下
    2021-08-08
  • C++ OpenMP简单介绍

    C++ OpenMP简单介绍

    这篇文章主要介绍了C++ OpenMP简介,OpenMP 还支持自定义数据类型的归约操作,需要通过omp declare reduction指令来声明自定义操作符和数据类型的归约方式,感兴趣的朋友一起看看吧
    2023-05-05
  • C++如何判断一个数是不是素数

    C++如何判断一个数是不是素数

    这篇文章主要介绍了C++如何判断一个数是不是素数,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • C++数组模拟之单链表与双链表和栈和队列的实现过程

    C++数组模拟之单链表与双链表和栈和队列的实现过程

    这篇文章主要介绍了C++数组模拟之单链表与双链表和栈和队列的实现过程,了解内部原理是为了帮助我们做扩展,同时也是验证了一个人的学习能力,如果你想让自己的职业道路更上一层楼,这些底层的东西你是必须要会的,跟随下文来具体了解吧
    2023-02-02

最新评论