do while(0)在宏定义中的应用

C语言宏定义中使用 do{}while(0) 的情形 先来看宏定义的一个经典例子;使用MFC;新建单文档工程,把宏定义在视类CPP文件头部; void CHongdoView::OnDraw(CDC* pDC) { CHongdoDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CString str1; int x = 101, y = 202; swap(x, y); //printf("%d %d\n" 阅读详情
看linux源码时,经常发现有宏定义用
#define XYZ \
do{...} while(0)
这是一个奇怪的循环,它根本就只会运行一次,为什么不去掉外面的do{..}while结构呢?原来这也是非常巧妙的技巧。在工程中可能经常会引起麻烦,而上面的定义能够保证这些麻烦不会出现。下面是解释:

假设有这样一个宏定义
#define macro(condition) \
if(condition) dosomething()

现在在程序中这样使用这个宏:
if(temp)
    macro(i);
else
    doanotherthing();

一切看起来很正常,但是仔细想想。这个宏会展开成:
if(temp)
    if(i) dosomething();
else
    doanotherthing();

这时的else不是与第一个if语句匹配,而是错误的与第二个if语句进行了匹配,编译通过了,但是运行的结果一定是错误的。

为了避免这个错误,我们使用do{….}while(0) 把它包裹起来,成为一个独立的语法单元,从而不会与上下文发生混淆。同时因为绝大多数的编译器都能够识别do{…}while(0) 这种无用的循环并进行优化,所以使用这种方法也不会导致程序的性能降低。

此外,这是为了含多条语句的宏的通用性。因为默认规则是宏定义最后是不能加分号的,分号是在引用的时候加上的。

在MFC的afx.h文件里面, 你会发现很多宏定义都是用了do...while(0)或do...while(false)。

为了看起来更清晰,这里用一个简单点的宏来演示:
#define SAFE_DELETE(p) do{ delete p; p = NULL } while(0)
假设这里去掉do...while(0),
#define SAFE_DELETE(p)   delete p; p = NULL;
那么以下代码:
if(NULL != p) SAFE_DELETE(p)
else   ...do sth...
就有两个问题,
1) 因为if分支后有两个语句,else分支没有对应的if,编译失败。
2) 假设没有else, SAFE_DELETE中的第二个语句无论if测试是否通过,会永远执行。
你可能发现,为了避免这两个问题,我不一定要用这个令人费解的do...while,  我直接用{}括起来就可以了
#define SAFE_DELETE(p)   { delete p; p = NULL;}
的确,这样的话上面的问题是不存在了,但是我想对于C++程序员来讲,在每个语句后面加分号是一种约定俗成的习惯,这样的话,以下代码:
if(NULL != p)  SAFE_DELETE(p);
else   ...do sth...
由于if后面的大括号后面加了一个分号,导致其else分支就无法通过编译了(原因同上),所以采用do...while(0)是做好的选择了。

如果使用名家的方法

#define SAFE_FREE(p)   do {free(p);p=NULL;}  while(0)

那么

if(NULL!=p)

        SAFE_FREE(p);

else

         do something

展开为

if(NULL!=p)

do

      { free(p);p=NULL;}

while(0);

else

        do something

好了 这样就一切太平了。

用树莓派搭建全功能NAS服务器(01):树莓派基础操作&OMV搭建 写在前面 对于文件互传来说,局域网和云盘的操作总是独立的,而且很难将两者的优势合为一体。如果想要集多种优势为一体,那么NAS应该就是较为完美的解决方案了。 在这个系列中我们尽量跳过一些枯燥的理论知识,专注于说明两件事:   1.NAS是什么&能做什么 2.搭建思路&怎么做   这中间也会涉及到一些方案的选择,同类方案我也会列出来和大家分享我已知的优缺点,有兴趣可以多种尝试。(侧重于软件) 虽然是用树莓派搭建的,但是对于debian linux系统下的NAS搭建有着很好的参 阅读详情

相关推荐

C#实战:如何从零构建一个轻量级软PLC梯形图编辑器(附完整源码)

本文详细介绍了如何使用C#从零开始构建一个轻量级软PLC梯形图编辑器。内容涵盖项目架构设计、GDI+图形渲染、编辑交互实现以及核心的扫描执行引擎开发,并提供了定时器、计数器等高级功能的实现思路与完整源码,为开发者深入工业自动化领域提供了实战指南。

4k5l6j7h8的博客 258

do...while(0) 在宏定义中的应用

 这是一个奇怪的循环,它根本就只会运行一次,为什么不去掉外面的do{...}while结构呢?我曾一度在心里把它叫做“怪圈”。原来这也是非常巧妙的技巧。在工程中可能经常会引起麻烦,而上面的定义能够保证这些麻烦不会出现。下面是解释:一方面假设有这样一个宏定义#define macro(condition) /if(condition) dosomething()现在在程序中这样使用这个宏:i

anuo的专栏 879

【环境搭建】使用openSfM+MVSNet重建稠密点云

本帖详细介绍了如何使用openSfM+MVSNet对真实采集的数据进行稀疏重建与稠密重建,并针对一些真实场景下可能遇到的问题进行了整理。

YuhsiHu的博客 1972

do{}while(0)

from: http://blog.youkuaiyun.com/chenhu_doc/article/details/856468 from: http://www.cnblogs.com/flying_bat/archive/2008/01/18/1044693.html 一、存在的意义 宏定义中的do...while(0) 构建复用库的时候,发现许多宏定义都使用了do...while(0),

wind_rabbit的专栏 1468

近几年预训练语音大模型汇总

语音大模型研究近年来取得显著进展,主要包括wav2vec 2.0(2020)、HuBERT(2021)、WavLM(2022)、Data2Vec(2022)、Whisper(2023)等代表性工作。这些模型采用自监督学习框架,通过掩码预测、对比学习等策略在大规模语音数据上预训练,可有效应用于语音识别、情感分析、疾病检测等下游任务。其中wav2vec 2.0首次将对比学习引入语音领域,Whisper通过68万小时弱监督数据实现强大的跨语言能力。这些突破为低资源语音任务提供了通用特征提取方案,推动了医疗语音分析

victory0431的博客 1780

机械臂标准DH建模及正运动学分析(以IRB4600型工业机械臂为例)

对于工业机械臂而言,运动学是不考虑力学特性的情况下对机械臂的几何参数与其位置、速度、加速度等运动特性的关系研究。DH建模是运动学的基础,全称为Denavit-Hartenberg建模方法,是一种广泛应用于机器人运动学中的建模技术。该方法通过在每个连杆上建立坐标系,并利用齐次坐标变换来实现连杆之间的坐标转换。通过依次变换,可以推导出末端执行器相对于基坐标系的位姿,从而建立机器人的运动学方程。以IRB4600型六自由度工业机械臂为例,选择标准DH建模方法,建立其正运动学模型。

chen_mp的博客 1万+

深入浅出 C 语言中的 do{..}while(0):宏定义的秘密武器

深入浅出 C 语言中的 do{..}while(0):宏定义的秘密武器在 C 语言编程中,我们常常会遇到while、for、if-else这些熟悉的循环和条件语句,它们逻辑清晰,用法直观。然而,有一种构造却总是让人摸不着头脑——do{..}while(0)。乍一看,它似乎只是while循环的变种,功能完全可以被替代,那为什么 C 语言之父 Dennis Ritchie 要设计它?它究竟有什...

Francis的博客 784

BPMN2.0规范及流程引擎选型方案

本文主要简明扼要的介绍了BPMN2.0规范的内容,可让读者快速度的了解BPMN2.0所涵盖的主要内容和图形样式。也较为详细的阐述了如何绘制标准的流程图,以及在软件层面中如何实现业务流程功能,和技术选型。

比特桃 1万+

c语言do while的好处,do{}while(0)宏定义的好处

通过do-while(0)宏定义将代码打包起来,成为一个独立的语法单元,从而不会引起上下文混淆,同时因为绝大多数的编译器都能够识别do{…}while(0)这种无用的循环并进行优化,所以使用这种方法也不会导致程序的性能降低下面就举几个上下文混淆的例子来说明do-while(0)的好处例1先看一个简单的宏#define SAFE_FREE(p) do {free(p);p=NULL;} while(...

weixin_29327977的博客 619

【DeepSeek应用实践】手把手教程:用 AnythingLLM + Ollama + DeepSeek-R1 搭建本地企业知识库

在众多的技术方案中,我们选择了 AnythingLLM、Ollama 和 DeepSeek-R1 这一组合来搭建本地知识库。Ollama 作为一个轻量级的本地化大语言模型部署工具,支持多种模型,易于安装和使用,能够快速在本地运行强大的语言模型。DeepSeek-R1 是一个专为知识库问答设计的检索增强生成(RAG)模型,它结合了检索和生成的优势,能够快速从知识库中检索相关信息并生成精准答案。而 AnythingLLM 则是一个用户友好的界面工具,可以方便地连接 Ollama 和 DeepSeek-R1

寻道AI,探索AI无限可能! 2569

MATLAB - ROS 2 工具箱入门教程

ROS 工具箱提供了一个连接 MATLAB® 和 Simulink® 与机器人操作系统(ROS 和 ROS 2)的接口。利用该工具箱,您可以设计 ROS 节点网络,并将 MATLAB 或 Simulink 生成的 ROS 节点与现有的 ROS 网络相结合。工具箱包括 MATLAB 函数和 Simulink 块,可通过记录、导入和回放 rosbag 文件来可视化和分析 ROS 数据。您还可以连接到实时 ROS 网络,访问 ROS 消息。

机器人控制与仿真应用 3068

C/C++预处理指令和宏定义#define及 do while(0)

本文主要记录了C/C++预处理指令 #define 宏定义 do/while(0) 什么时候使用

一丁的博客 1164

为YOLOv11引入自适应特征融合模块(ASFF)

本文探讨了在YOLOv11中引入ASFF(自适应空间特征融合)模块以解决多尺度目标检测性能不均衡的问题。作者分析了传统FPN固定融合策略的缺陷,详细介绍了ASFF模块的实现原理,包括动态权重生成网络设计和特征融合机制。通过将ASFF集成到YOLOv11颈部网络,实现了特征在双向流动时的自适应融合,在复杂场景下mAP提升1.2%而推理时间仅增加3-5ms。文章还分享了训练调参技巧和部署注意事项,指出ASFF特别适合交通监控等目标尺度变化大的场景,但强调需根据实际需求平衡模型复杂度与性能。最后提供了工程实践建议

as1225120794的博客 321

宏定义中使用do{}while(0)的好处

#define MACRO_NAME(para) do{macro content}while(0)的格式,总结了以下几个原因:1,空的宏定义避免warning:#define foo() do{}while(0)2,存在一个独立的block,可以用来进行变量定义,进行比较复杂的实现。3,如果出现在判断语句过后的宏,这样可以保证作为一个整体来是实现:#define foo(

liliangbao的专栏 2万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

do...while(0)的妙用

http://www.cppblog.com/SmartPtr/archive/2007/07/03/27443.html   By SmartPtr(http://www.cppblog.com/SmartPtr/)     在C++中,有三种类型的循环语句:for, while, 和do...while, 但是在一般应用中作循环时, 我们可能用for和while要多一些,do..

victoryckl的专栏 688

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

do{}while(0)实现宏定义

do{}while(0)实现宏定义 在定义宏尤其是定义多语句宏时,经常会看见如下定义: #define compute(a,b) do {add(a,b);sub(a,b);} while(0) 这样定义的宏有2个好处,它可以不受大括号、分号的影响,不论在什么情况下使用宏,宏都可以按照定义者的原本设计运行而不会出错;同时可以避免出现空的宏定义。 在定义多语句宏时,经常会出现分号导致运行结果出...

weixin_43814616的博客 1025

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

宏定义代码块之 do{} while(0) 的使用

在 main 函数中,我们可以像使用单个语句一样使用 MY_MACRO ,并且后续的代码不会受到宏定义中的多条语句的影响。主要的目的是为了解决宏定义在使用时可能引发的一些问题,例如宏定义中的分号和大括号的使用。}while(0),将你的代码写在里面,里面可以定义变量而不用考虑变量名会同函数之前或者之后的重复。,允许在宏定义中使用局部变量。总而言之, do{} while(0) 的作用是为了解决宏定义在使用时可能引发的一些问题,确保宏定义可以作为单个语句使用,并且在逻辑上看起来像是一个语句。

weixin_53592457的博客 2289

C++ do...while(0) do...while(false)的妙用

转载自网络,如有版权问题,请和本人联系,谢谢! do...while(0) do...while(false)的妙用    在C++中,有三种类型的循环语句:for, while, 和do...while, 但是在一般应用中作循环时, 我们可能用for和while要多一些,do...while相对不受重视。    但是,最近在读我们项目的代码时,却发现了do...while的一些十分

我相信分享也是一种能力 2706

do{}while(0)的妙用

do...while(0)的妙用 在C++中,有三种类型的循环语句:for, while, 和do...while, 但是在一般应用中作循环时, 我们可能用for和while要多一些,do...while相对不受重视。 但是,最近在读我们项目的代码时,却发现了do...while的一些十分聪明的用法,不是用来做循环,而是用作其他来提高代码的健壮性。 1. do...while

铸剑娃的专栏 3504

do...while(0)妙用

1、使宏定义更安全 2、在需要错误处理时,减少代码冗余度和goto的使用 1、假设有如下代码: #define p {A;B} ... if(COND) p;//不符合编程习惯————通常语句后加分号 else .... 当然,如果上述语句不加分号,是不会出现问题的。用do…while(0)的好处是可以将加分号贯彻到底。 #define p do{A;B;}while(0) 2、处理错误时...

jojozym的博客 328

java中的CondVal_转载:do...while(0)的妙用

MTK中有很多有关do...while(0)的应用,刚开始可能有很多人不太明白为什么使用do...while(0),似乎不加do...while(0),该部分的代码也会只执行一次,其实do...while(0)是出于优化代码考虑的.do...while(0)并不是程序员为了炫耀自己的技术而展示的奇巧淫技,而是有实实在在的功能用途的.兹转载一篇文章共同研究.在C++中,有三种类型的循环语句:for,...

weixin_36048512的博客 240

do...while(0)在宏定义中的巧妙用法

2014年08月14日 20:04:20 luoweifu 阅读数:16058 标签: C++ 宏 收起 个人分类: C++ 版权声明:本文为博主原创文章,未经博主允许不得用于任何商业用途,转载请注明出处。 https://blog.youkuaiyun.com/luoweifu/article/details/38563161 大家都知道,do…while(condition)可以表示循环,但你有没有遇...

u010029439的博客 393

do{}while(0)宏定义的好处

<br /> <br />转载自:http://blog.ednchina.com/fpga2006/34658/message.aspx<br /> #define MACRO_NAME(para) do{macro content}while(0)<br /> 的格式,总结了以下几个原因:<br />  <br /> 1,空的宏定义避免warning:<br /> #define foo() do{}while(0)<br />  <br /> 2,存在一个独立的block,可以用来进行变量定义,进行比

miyunhong的专栏 652

do...while(0) do...while(false)的妙用

do...while(0) do...while(false)的妙用     在C++中,有三种类型的循环语句:for, while, 和do...while, 但是在一 般应用中作循环时, 我们可能用for和while要多一些,do...while相对不受重视。     但是,最近在读我们项目的代码时,却发现了do...while的一些十分聪明的用法,不是用来做循环,而是用作其他来提高代码

free4wuyou的专栏 657
上一篇: static_cast, dynamic_cast, reinterpret_cast, const_cast区别比较
下一篇: linux 内存分配机制 (转)
otuhacker
博客等级 码龄18年 21粉丝 84原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值