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\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;
}

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

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/21288.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

肝一肝设计模式【八】-- 外观模式

系列文章目录 肝一肝设计模式【一】-- 单例模式 传送门 肝一肝设计模式【二】-- 工厂模式 传送门 肝一肝设计模式【三】-- 原型模式 传送门 肝一肝设计模式【四】-- 建造者模式 传送门 肝一肝设计模式【五】-- 适配器模式 传送门 肝一肝设计模式【六】-- 装饰器模式 传送门 肝…

mysqlbinlog delete恢复成insert

不小心把数据删掉了 首先要拿到binlog文件 执行以下命令行 /usr/local/mysql/bin/mysqlbinlog --base64-outputdecode-rows --start-datetime“2023-05-19 09:01:32” --stop-datetime“2023-05-19 09:01:35” -v /Users/zylong/Downloads/mysql-bin.003178 --result-file/Use…

蓝桥:前端开发笔面必刷题——Day1 数组(一)

文章目录 &#x1f4cb;前言&#x1f3af;数组中重复的数字&#x1f4da;题目内容✅解答 &#x1f3af;两数之和&#x1f4da;题目内容✅解答 &#x1f3af;替换空格&#x1f4da;题目内容✅解答 &#x1f3af;二维数组中的查找&#x1f4da;题目内容✅解答 &#x1f4dd;最后 …

C#串口通信从入门到精通(14)——多个串口接收数据

文章目录 前言1、多串口数据的接收2、源码前言 我们在开发串口通信程序时,有时候会需要连接不止一个串口,这时候该怎么写程序呢?本文就来介绍多个串口数据的接收 1、多串口数据的接收 我们在之前的专栏中介绍了串口数据的发送,当时有提到过,我们是通过创建一个SerialPo…

unity,如何让人物随着鼠标滑动而转向?

介绍 unity&#xff0c;如何让人物随着鼠标滑动而转向&#xff1f; 方法 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems;public class PlayerMovement : MonoBehaviour {public float speed 6f; …

RK3588平台开发系列讲解(进程篇)Linux文件系统数据结构

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、Linux 文件系统数据结构有哪些二、超级块结构 spuer_block三、目录 dentry四、文件索引结点 inode五、打开的文件 file沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 本篇将介绍 Linux 文件系统数据结构…

IIC总线通讯协议学习

​ IIC(最简单的总线通讯,简单意味着通用和普适性) iic通讯一般采用一主多从的方式.同一时间要么在发送信息,要么在读取信息(半双工通讯) ​​​​​​​​​​​​​​ ​​​​ ​​​ 标准的写数据帧&#xff08;主机向从机写数据) 解释以上的写数据帧 S:起始信号(在SCL…

什么是投入产出比(ROI)以及如何提升投入产出比?

投入产出比&#xff08;ROI&#xff09;是一种衡量企业或项目投资效益的指标&#xff0c;它可以帮助企业评估投资回报情况&#xff0c;并制定更加明智的投资决策。本文将为大家介绍什么是投入产出比&#xff08;ROI&#xff09;以及如何提升投入产出比。 一、什么是投入产出比&…

6年心得,从功能测试到测试开发,送给在测试路上一路走到黑的你

蓦然回首&#xff0c;软件测试风风雨雨的这就几年&#xff0c;起初每天的工作只是鼠标点点点&#xff0c;我还真不知道怎么办&#xff0c;闲的时候真的怀疑自己的存在价值&#xff0c;每天拿着7000的工资&#xff0c;飘荡在繁华的深圳&#xff0c;吃不饱也饿不死&#xff0c;未…

【UDS】诊断故障代码老化机制

文章目录 简介相关术语1. 老化计数器 Ageing counter2. 诊断故障代码已老去 DTC aged3. 已老去计数器 Aged counter4. 操作循环 Operation cycle5. 诊断故障代码老化机制 DTC aging mechanism 总结 ->返回总目录<- 简介 诊断故障代码&#xff08;DTC&#xff09;一旦生…

软件设计师考试笔记,已通过

目录 系统可靠度 外部实体 内聚类型 编译过程 逆波兰式 前驱图 scrum框架模型 编译和解释 有限自动机 聚簇索引和非聚簇索引 二叉树的前序,中序,后序遍历 动态规划贪心算法 算法 01背包问题 系统可靠度 1. 串联部件可靠度 串联部件想要这条路走通&#xff0c;只有…

062:cesium设置泛光折线材质(material-6)

第062个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中设置泛光折线材质,请参考源代码,了解PolylineGlowMaterialProperty的应用。 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共89行)相关API参考:专…

开发框架Furion之WebApi+SqlSugar (一)

目录 1.开发环境 2.项目创建 2.1创建WebApi主项目 2.2 创建Start类库 2.3创建Model实体类库 2.4创建Application仓储业务类库 2.5创建Unility通用方法类库 3.基础功能配置 3.1 Model实体对象与数据表映射 3.2 基类仓储及动态Api接口配置 3.3 数据库IOC注册 3.4 Star…

JDK源码阅读环境搭建

本次针对jdk8u版本的搭建 1.新建项目 新建java项目JavaSourceLearn &#xff0c;这里我创建的是maven 2.获取JDK源码 打开Project Structure 找到本地JDK安装位置将src.zip解压到项目java包中 整理下项目结构&#xff0c;删除用不到的目录 提示: 添加源码到项目之后首次运行…

从零玩转设计模式之原型模式-yuanxingmoshi

title: 从零玩转设计模式之原型模式 date: 2022-12-11 20:05:35.488 updated: 2022-12-23 15:35:44.159 url: https://www.yby6.com/archives/yuanxingmoshi categories: - 设计模式 tags: - 设计模式 - 原型模式 什么是原型模式设计模式? 原型模式是一种软件设计模式&#…

公司招了一个00后,以为是个小年轻,没想到人家是个卷王...

公司前段缺人&#xff0c;也面了不少测试&#xff0c;结果竟然没有一个合适的。一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资也不低&#xff0c;面试的人很多&#xff0c;但平均水平很让人失望。 令我印象最深的是一个00后测试员&#xff0c;…

【Linux高级 I/O(2)】如何使用阻塞 I/O 与非阻塞 I/O?——select()函数

上次我们虽然使用非阻塞式 I/O 解决了阻塞式 I/O 情况下并发读取文件所出现的问题&#xff0c;但依然不够完美&#xff0c;使得程序的 CPU 占用率特别高。解决这个问题&#xff0c;就要用到本文将要介绍的 I/O 多路复用方法。 何为 I/O 多路复用 I/O 多路复用&#xff08;IO m…

AI 将完全取代前端开发吗?

注&#xff1a;今晨&#xff0c;我浏览 Medium&#xff0c;看到了篇颇为标题党的文章&#xff0c;于是我就将它抛给了 ChatGPT。本篇文章全部由 ChatGPT 所写。同时&#xff0c;我也请 ChatGPT 分享了它对此的观点。 最近&#xff0c;我的同事向我讲述了他与他老板的一次谈话。…

Python机器学习:Scikit-learn和TensorFlow的应用和模型设计

一、引言 Python在机器学习领域中已经成为非常受欢迎的编程语言。Scikit-learn和TensorFlow是Python中应用最广泛的两个机器学习库&#xff0c;它们提供了丰富的机器学习算法和工具&#xff0c;帮助开发人员轻松地构建和训练机器学习模型。本文将详细介绍Scikit-learn和Tensor…

功率放大器的选型原则和方法是什么

功率放大器是一种能够将低电平信号放大到足够高的电平以驱动负载的电子器件。在各种电子设备中&#xff0c;功率放大器被广泛应用&#xff0c;如音响系统、电视广播、汽车音响、射频通信等。因此&#xff0c;正确选型功率放大器非常重要&#xff0c;可以提高设备的性能和可靠性…