Cherno C++ P55 宏
这篇文章我们讲一下C++当中的宏。其实接触过大型项目的朋友可能都被诡异的宏折磨过。
宏是在预处理当中,通过文本替换的方式来实现一些操作,这样可以不用反复的输入代码,帮助我们实现自动化。至于预处理的过程,其实就是文本编辑,这个在之前的文章中有提到过。
替换的具体内容,可能是普通文本,也可以是参数变量等各种东西,可以说,就没有什么是不能够被宏替换掉的,我们可以拿来替换非常复杂的内容。但是需要注意的是,我们不希望拿宏来替换太多与C++特性有关的代码,这样并不是一个好的做法,因为会降低代码的可读性,虽然这样做是没有任何问题的。
举个例子,我们用宏替换到我们常用的cin.get()语句:
#include<iostream>
#include<string>
#define WAIT std::cin.get()int main() {std::cout << "Hello World!" << std::endl;WAIT;
}
这样写当然是可以的,是能够编译通过的,但是这种写法是很傻的。因为cin.get()是非常常用的语句,但是使用一个WAIT来替换它,反而会降低代码的可读性,让其他人看得一头雾水。
当然,分号也可以是宏的一部分,如果想的话也可以把分号写在宏里面,那么就不用在代码里面再写分号了。
接下来我们看看如何在宏当中定义函数。
#include<iostream>
#include<string>
#define LOG(x) std::cout<< x << std::endl;int main() {LOG("Hello World!")std::cin.get();
}
我们运行代码就会发现,我们正常的完成了打印,所以和实际写cout效果是一样的。
那么我们可以如何用宏帮助我们?一个有趣的实例就是在我们的日志类当中,我们希望在debug状态下打印出我们需要的信息,但是在release版本当中不希望那么多东西都被打印到控制台上,那么如何能够区分debug还是release?在不同模式下函数应该是什么样子的?这些我们就都可以用到宏来进行控制。
首先我们需要打开属性,然后找到预处理界面,然后分别为debug和release两个配置添加不同的宏,如图所示:

我们在debug和release模式下分别定义PR_DEBUG和PR_RELEASE两个宏,这样我们就有了区分debug和release两个模式的工具。然后我们就可以通过宏来控制我们是否需要打印:
#ifdef PR_DEBUG
#define LOG(x) //这里填写我们需要的函数定义
#else
#define LOG(x)
#endif
如上述代码所示,我们可以在debug模式下让LOG函数真的为我们输出一些东西,但是在release模式下,LOG就不代表任何代码了,也就是说切换到release时,LOG处都会变成空白,宏自动的为我们删除了在release时需要被删除的代码,这一点是非常nice的。
但是这样使用也是有一点问题的,因为有的时候我们不想使用某个宏了,那我们还得去删除,就很麻烦,最好的情况是给宏赋一个值,然后我们不想使用宏的时候,可以直接修改这个宏的值,那么这个宏就被禁用了。首先我们在设置当中为我们的宏赋值:

如图所示,我们把PR_DEBUG赋值为1,然后我们在代码当中可以直接这样写:
#if PR_DEBUG == 1
来判断是不是在debug模式下。如果我们想要禁用这个宏,只需要
#define PR_DEBUG 0
就可以禁用这个宏了。
除此之外,我们还可以用宏来禁用一整块代码,如下所示:
#if 0LOG("Hello World!")
#endif
这样中间部分代码就都无效了。
如果我们想要代替多行代码,可以用反斜线 \ 来替代,反斜线就是分行的转义。
宏最常用的地方就是用来帮助我们debug,还可以自动查错,也可以帮助跟踪内存的使用情况。但是如果滥用宏,确实会导致代码可读性大幅降低,所以我们还是要慎重使用宏。以上就是本文的全部内容了,希望大家喜欢!
相关文章:
Cherno C++ P55 宏
这篇文章我们讲一下C当中的宏。其实接触过大型项目的朋友可能都被诡异的宏折磨过。 宏是在预处理当中,通过文本替换的方式来实现一些操作,这样可以不用反复的输入代码,帮助我们实现自动化。至于预处理的过程,其实就是文本编辑&am…...
MybatisMybatisPllus公共字段填充与配置逻辑删除
Mybatis/MybatisPllus公共字段填充与配置逻辑删除 在开发过程中,很多时候需要处理一些公共字段,例如:创建时间、修改时间、状态字段等。这些字段通常会在插入或更新数据时进行填充,以便记录数据的变化和状态。同时,逻…...
VS Code User和System版区别【推荐使用System版本】and VSCode+Keil协同开发之Keil Assistant
VS Code User和System版区别 Chapter1 VS Code User和System版区别1. 对于安装而言2. 结束语 Chapter2 VS Code 安装、配置教程及插件推荐插件: Chapter3 VSCodeKeil协同开发之Keil Assistant1. 效果展示2. Keil Assistant简介3. Keil Assistant功能特性4. 部署步骤…...
MongoDB:listDatabases failed : not master and slaveOk=false
个人博客地址:MongoDB:listDatabases failed : not master and slaveOkfalse | 一张假钞的真实世界 异常描述 如果在MongoDB的SECONDARY上查询数据时会报如下错误信息: > show databases; 2018-09-20T17:40:55.3770800 E QUERY [thread…...
Python的那些事第二十二篇:基于 Python 的 Django 框架在 Web 开发中的应用研究
基于 Python 的 Django 框架在 Web 开发中的应用研究 摘要 Django 是一个基于 Python 的高级 Web 框架,以其开发效率高、安全性和可扩展性强等特点被广泛应用于现代 Web 开发。本文首先介绍了 Django 的基本架构和核心特性,然后通过一个实际的 Web 开发项目案例,展示了 Dj…...
【ISO 14229-1:2023 UDS诊断(会话控制0x10服务)测试用例CAPL代码全解析④】
ISO 14229-1:2023 UDS诊断【会话控制0x10服务】_TestCase04 作者:车端域控测试工程师 更新日期:2025年02月15日 关键词:UDS诊断、0x10服务、诊断会话控制、ECU测试、ISO 14229-1:2023 TC10-004测试用例 用例ID测试场景验证要点参考条款预期…...
图论入门算法:拓扑排序(C++)
上文中我们了解了图的遍历(DFS/BFS), 本节我们来学习拓扑排序. 在图论中, 拓扑排序(Topological Sorting)是对一个有向无环图(Directed Acyclic Graph, DAG)的所有顶点进行排序的一种算法, 使得如果存在一条从顶点 u 到顶点 v 的有向边 (u, v) , 那么在排序后的序列中, u 一定…...
【CXX】2 CXX blobstore客户端说明
本示例演示了一个调用blobstore服务的C客户端的Rust应用程序。事实上,我们会看到两个方向的调用:Rust到C以及C到Rust。对于您自己的用例,您可能只需要其中一个方向。 示例中涉及的所有代码都显示在此页面上,但它也以可运行的形式提…...
HTTP相关面试题
HTTP/1.1、HTTP/2、HTTP/3 演变 HTTP/1.1 相比 HTTP/1.0 提高了什么性能? HTTP/1.1 相⽐ HTTP/1.0 性能上的改进: 使⽤长连接的⽅式改善了 HTTP/1.0 短连接造成的性能开销。⽀持管道(pipeline)网络传输,只要第⼀个请…...
关于XML映射器的基本问题
前言 XML 映射器是 MyBatis 中用于定义 SQL 语句及其与 Java 对象映射关系的 XML 文件。它通过 XML 配置将数据库操作与 Java 代码分离,使 SQL 语句更易维护和管理。 主要作用 定义 SQL 语句:在 XML 中编写 SQL 查询、插入、更新和删除操作。 映射结果…...
【MyBatis】预编译SQL与即时SQL
目录 1. 以基本类型参数为例测试#{ }与${ }传递参数的区别 1.1 参数为Integer类型 1.2 参数为String类型 2. 使用#{ }传参存在的问题 2.1 参数为排序方式 2.2 模糊查询 3. 使用${ }传参存在的问题 3.1 SQL注入 3.2 对比#{ } 与 ${ }在SQL注入方面存在的问题 3.3 预编译…...
Python--正则表达式
1. 日志打印与终端颜色控制 1.1 使用 loguru 打印日志 from loguru import loggerlogger.debug("调试信息") logger.info("普通信息") logger.warning("警告信息") logger.error("错误信息") logger.success("成功信息"…...
【java面试】线程篇
1.什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。 2.线程和进程有什么区别? 线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任…...
分布式光纤传感:为生活编织“感知密网”
分布式光纤测温技术虽以工业场景为核心,但其衍生的安全效益已逐步渗透至日常生活。 分布式光纤测温技术(DTS)作为一种先进的线型温度监测手段,近年来在多个领域展现了其独特的优势。虽然其核心应用场景主要集中在工业、能源和基础…...
cmake Qt Mingw windows构建
今天教大家怎么在windows构建qt应用使用cmd命令行,而不是一键通过QtCreator一键构建。首先我们用qtcreator创建一个模板程序(PS:记得在安装qt时要悬着mingw套件,如果安装太慢可以换源) 输入以下的命令: mkdir build …...
无人机信号调制技术原理
一、调制技术的必要性 频谱搬移:将低频的基带信号搬移到高频的载波上,便于天线辐射和传播。 信道复用: 利用不同的载波频率或调制方式,实现多路信号同时传输,提高信道利用率。 抗干扰: 通过选择合适的调…...
书评与笔记:《如何有效报告Bug》
文章目录 书评笔记核心原则1. 首要目标:让程序员亲眼看到问题2. 次要目标:详细描述问题3. 保持冷静,避免误操作4. 提供额外信息5. 清晰、准确地表达 实用建议不要自作聪明地诊断问题类比:看医生时的症状描述程序员的心理 总结 原文…...
3.【线性代数】——矩阵乘法和逆矩阵
三 矩阵乘法和逆矩阵 1. 矩阵乘法1.1 常规方法1.2 列向量组合1.3 行向量组合1.4 单行和单列的乘积和1.5 块乘法 2. 逆矩阵2.1 逆矩阵的定义2.2 奇异矩阵2.3 Gauss-Jordan 求逆矩阵2.3.1 求逆矩阵 ⟺ \Longleftrightarrow ⟺解方程组2.3.2 Gauss-Jordan求逆矩阵 1. 矩阵乘法 1.…...
[JVM篇]虚拟机性能监控、故障处理工具
虚拟机性能监控、故障处理工具 基础故障处理工具 jps(JVM Peocess Status Tool - 虚拟机进程状况工具) jstat(JVM Statistics Monitoring Too - 虚拟机统计信息监视工具) jinfo( Configuration info for Java - Java配置信息工具) jmap(Memory Map for…...
UniApp 中 margin 和 padding 属性的使用详解
margin 属性的作用与使用 margin 属性用于设置元素的外边距,也就是元素与其他元素之间的距离。它可以分别设置元素四个方向(上、右、下、左)的外边距,也支持使用简写形式来一次性设置多个方向的外边距。 <template><view…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
