do{}while(0)的妙用

模仿R星官网(响应式) 小白一个,初学编程编程,练习一下编程能力在网上找了一个游戏官网,模仿R星官网。 阅读详情

do...while(0)的妙用

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

1. do...while(0)消除goto语句。
通常,如果在一个函数中开始要分配一些资源,然后在中途执行过程中如果遇到错误则退出函数,当然,退出前先释放资源,我们的代码可能是这样:
version 1

bool Execute()
{
   
//分配资源

   int *p = new int" _msthash="1428141" _mstchunk="true">int *p = new int ;
   
bool bOk(true" _msthash="1428142" _mstchunk="true">bool bOk(true
);

   
//执行并进行错误处理

bOk = func1();
   
if(!
bOk)
   {
delete p;
p
=
NULL;
      
return false" _msthash="1462539" _mstchunk="true">return false
;
   }

bOk
=
func2();
   
if(!
bOk)
   {
delete p;
p
=
NULL;
      
return false" _msthash="1465334" _mstchunk="true">return false
;
   }

bOk
=
func3();
   
if(!
bOk)
   {
delete p;
p
=
NULL;
      
return false" _msthash="1463085" _mstchunk="true">return false
;
   }

   
//
 ..........

   
//执行成功,释放资源并返回

delete p;
p
=
NULL;
    
return true" _msthash="1465321" _mstchunk="true">return true
;
   
}


这里一个最大的问题就是代码的冗余,而且我每增加一个操作,就需要做相应的错误处理,非常不灵活。于是我们想到了goto:
version 2

bool Execute()
{
   
//分配资源

   int *p = new int" _msthash="1428143" _mstchunk="true">int *p = new int ;
   
bool bOk(true" _msthash="1428144" _mstchunk="true">bool bOk(true
);

   
//执行并进行错误处理

bOk = func1();
   
if(!bOk) goto" _msthash="1430325" _mstchunk="true">if(!bOk) goto
errorhandle;

bOk
=
func2();
   
if(!bOk) goto" _msthash="1430871" _mstchunk="true">if(!bOk) goto
errorhandle;

bOk
=
func3();
   
if(!bOk) goto" _msthash="1461421" _mstchunk="true">if(!bOk) goto
errorhandle;

   
//
 ..........

   
//执行成功,释放资源并返回

delete p;
p
=
NULL;
    
return true" _msthash="1463657" _mstchunk="true">return true
;

errorhandle:
delete p;
p
=
NULL;
    
return false" _msthash="1464216" _mstchunk="true">return false
;
   
}


代码冗余是消除了,但是我们引入了C++中身份比较微妙的goto语句,虽然正确的使用goto可以大大提高程序的灵活性与简洁性,但太灵活的东西往往是很危险的,它会让我们的程序捉摸不定,那么怎么才能避免使用goto语句,又能消除代码冗余呢,请看do...while(0)循环:
version3

bool Execute()
{
   
//分配资源

   int *p = new int" _msthash="1428145" _mstchunk="true">int *p = new int ;

   
bool bOk(true" _msthash="1428146" _mstchunk="true">bool bOk(true
);
   
do

   {
      
//执行并进行错误处理
bOk = func1();
      
if(!bOk) break" _msthash="1430872" _mstchunk="true">if(!bOk) break
;

bOk
=
func2();
      
if(!bOk) break" _msthash="1461422" _mstchunk="true">if(!bOk) break
;

bOk
=
func3();
      
if(!bOk) break" _msthash="1461980" _mstchunk="true">if(!bOk) break
;

      
// ..........


   }
while(0" _msthash="1463098" _mstchunk="true">while(0 );

    
//释放资源

delete p;
p
=
NULL;
    
return
bOk;
   
}


“漂亮!”, 看代码就行了,啥都不用说了...

2 宏定义中的do...while(0)
如果你是C++程序员,我有理由相信你用过,或者接触过,至少听说过MFC, 在MFC的afx.h文件里面, 你会发现很多宏定义都是用了do...while(0)或do...while(false), 比如说:
#define AFXASSUME(cond) do { bool __afx_condVal=!!(cond); ASSERT(__afx_condVal); __analysis_assume(__afx_condVal); } while(0)
粗看我们就会觉得很奇怪,既然循环里面只执行了一次,我要这个看似多余的do...while(0)有什么意义呢?
当然有!
为了看起来更清晰,这里用一个简单点的宏来演示:
#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...

其else分支就无法通过编译了(原因同上),所以采用do...while(0)是做好的选择了。

也许你会说,我们代码的习惯是在每个判断后面加上{}, 就不会有这种问题了,也就不需要do...while了,如:
if(...)
{
}
else
{
}

诚然,这是一个好的,应该提倡的编程习惯,但一般这样的宏都是作为library的一部分出现的,而对于一个library的作者,他所要做的就是让其库具有通用性,强壮性,因此他不能有任何对库的使用者的假设,如其编码规范,技术水平等。

原文连接:http://www.cnblogs.com/flying_bat/archive/2008/01/18/1044693.html

C++中do...while(0)的妙用 一点睛 do{...}while(condition)可以表示循环,但你有没有遇到在一些地方宏定义中可以不用循环的地方,也用到了do{...}while(condition),比如有这样的宏: #define Foo(x) do{\ printf("first statement\n");\ printf("second statement\n");\ }while(0) ... 阅读详情

相关推荐

用AI助手Cursor轻松自动生成流程图

通过 Cursor + Mermaid,我们可以快速、准确地自动生成流程图,上面演示的例子部分流程图可能比较丑,我们可以通过流程图软件导入Mermaid代码,然后手动进行微调就可以了,如果你对美观要求不是特别多,可以直接用,这将极大地提升代码可视化和架构设计的效率。

呱牛 Just do IT 1939

后端对标签字符串进行操作

测试

weixin_57087321的博客 546

手把手教你用Trae配置Python开发环境(含Claude 3.5代码生成实战)

本文详细介绍了如何使用字节跳动推出的Trae智能开发环境配置Python开发环境,并实战演示了Claude 3.5代码生成功能。从环境准备到项目初始化,再到AI辅助编码和调试优化,全面展示了Trae在提升开发效率方面的强大能力,特别适合Python开发者快速搭建项目和解决复杂问题。

weixin_28309571的博客 977

HTML爱心代码超好看

就爱你怎么办

weixin_71512510的博客 1963

高级Salesforce开发面试题

自定义设置允许您创建自定义数据集,以及为组织、配置文件或特定用户创建和关联自定义数据。自定义元数据类似于自定义设置,但是自定义元数据类型中的记录被视为元数据而不是数据。自定义设置有列表和层次自定义设置两种。自定义元数据中没有此类类型。此外,自定义元数据不支持基于用户配置文件或特定用户的层次结构类型的数据。自定义设置现在不再支持关系字段。但您可以在自定义元数据对象之间创建查找。元数据查询不占用查询sql次数的限制。

weixin_45663522的博客 1242

海思HiMPP开发避坑指南:MMZ内存与系统内存傻傻分不清?一个例子讲透

本文深入解析海思HiMPP开发中MMZ内存与系统内存的关键差异与应用场景,帮助开发者避免常见的内存混淆问题。通过实际案例和性能对比,详细介绍了MMZ内存的特性和优化策略,提升多媒体处理效率。

weixin_30772105的博客 468

【Semantic框架学习日志】(7)segment的使用

文章目录一、组件的简单介绍二、组件的一些用法(1)标准输入框(2)交互性(焦点式)输入框(3)加载中输入框(4)禁用输入框(5)错误提示型输入框(6)带图标型输入框(7)标签型输入框(7)动作型输入框 一、组件的简单介绍     通过输入框,实现用户与界面之间的交互。 优点:组件可以根据它们出现的屏幕大小响应性地调整其最大宽度,方便了响应式页面的开发 二、组件的一些用法 (1)标准输入框 <div class="ui input"> <input type="text" pla

weixin_50765519的博客 1316

UE4_SpeedTree Shader源码分析

目录 1.UMaterialExpressionSpeedTree::Compile 2.Compiler->SpeedTree 3.GetSpeedTreeVertexOffset 4.Scene中的SpeedTree应用 (Scene->UpdateSpeedTreeWind) 5.GetSpeedTreeVertexOffsetInner 由于之后做风场,也需要在S...

zzgyy123的专栏 2631

java.util包详解

介绍Java的实用工具类库java.util包。在这个包中,Java提供了一些实用的方法和数据结构。本章介绍Java的实用工具类库java.util包。在这个包中,Java提供了一些实用的方法和数据结构。例如,Java提供日期(Data)类、日历(Calendar)类来产生和获取日期及时间,提供随机数(Random)类产生各种类型的随机数,还提供了堆栈(Stack)、向量(Vector) 、位集合

8万+

302.QoS实现工具之MQC

QoS 技术可以对网络中报文进行分类处理,根据优先级提供不同的差分服务,如何实现这种差分服务呢?我们有一种强大的配置方法 - 模块化 QoS 命令行 MQC(Modular QoS Command-Line)。下面就来介绍一下 MQC。

迷逝 1393

52、基于格的具有解密密钥暴露抗性的可撤销(分层)身份基加密方案

本文提出了首个基于格的具有解密密钥暴露抗性(DKER)的可撤销分层身份基加密(RHIBE)方案。通过引入分层密文、分层解密密钥和级别转换密钥等创新工具,克服了格结构与传统密钥重新随机化属性不匹配的难题。该方案不仅支持可扩展的密钥撤销机制,还具备密钥委托功能,为后量子密码学领域的发展提供了新的思路和方法。

efc12345678的博客 123

do-while(0)妙用

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

happyforest的专栏 1100

矩阵奇异值分解算法(SVD)的导数 / 灵敏度分析

设矩阵X∈Rm×nX∈Rm×nXUΣV⊤XUΣV⊤U∈Rm×mU∈Rm×m为左奇异向量矩阵;V∈Rn×nV∈Rn×n为右奇异向量矩阵;Σdiag⁡σ1σ2σrΣdiagσ1​σ2​σr​为奇异值对角阵(rrank⁡XrrankX我们关心:当XXX发生微小扰动dXdX时,UΣVUΣV如何变化?dXdUΣV⊤dX。

qq_36812406的博客 1751

do-while(0)的妙用

经常会遇到一段程序或者宏定义里面用到do-while(0),当时不知道为什么要这么用,既然只执行一次为何非要添加循环。 实际体会后才感觉这一步用的狠妙。有网友总结的挺好,贴出来。谢谢大神。 https://blog.youkuaiyun.com/lplp90908/article/details/50405880 在C++中,有三种类型的循环语句:for, while, 和do...while, 但是在一般应用中作循环时, 我们可能用for和while要多一些,do...while相对不受重视。 但是,最...

fhb1922702569的博客 380

WINCC7.3破解文件

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

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

do…while(0)的妙用

一、开始 循环在程序中是不可少的,要么for, while...do,do...while, 但它都有自己的循环条件,在一些Linux的库中,MFC中常常会有do...while(0),或者do...while(FALSE)的宏,有什么用呢?不是用来循环,是用来提高代码的健壮性。闲来无事,总结一下。   二、妙用总结 1.使程序结构简单 1: //------------------

bytxl的专栏 1013

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

do while(0)的妙用

do while(0)的妙用 do while(0);就如同一个花括号,具有独立的作用域,花括号所表示的符合语句是一个整体,do while(); 语句同样是一个整体,同样可以在if 等条件语句后直接使用。但是后所不同的是,do while(); 作为循环语句还可以使用break 跳出循环,程序执行流也就随之来到了do while(0);的下一条语句。下面就来介绍 do while(0);的三条...

Hello_MyDream的博客 3万+

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

do...while(0)的妙用

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

1648

do while(0)妙用 内核中常见代码

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

微信号codek2 专注于 Android 开源项目源码解析 开源项目分享 1501

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)的妙用 在学习第一门编程语言时,就已经介绍了顺序分支、条件分支、循环分支。比如循环分支有for、while、do-while语句。在随后的学校及工作中,如果手工循环一般使用for、while,很少使用do-while,感觉用处不大,但现在看来,do-while大有用途。 1. 帮助定义复杂的宏以避免错误 举例来说,假设你需要定义这样一个宏: #defi...

BangBang的博客 177

do{}while(0)的妙用

在linux内核代码中,经常看到do...while(0)的宏,do...while(0)有很多作用,下面举出几个: 1、避免goto语句: 通常,如果一个函数开始要分配一些资源,然后如果在中途遇到错误则要退出函数,当然,退出前要释放资源,我们的代码可能如下:  1 #defien N 10 2 3 bool Execute() 4 { 5 // 分配资

xidian208的专栏 425

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

do{ }while(0)的妙用

do{ }while(0)的妙用 转载: https://www.zhihu.com/question/24386599/answer/1297723714. 在嵌入式开发中,宏定义非常强大也非常便捷,如果正确使用可以让你的工作事半功倍。然而,在很多的C程序中,你可能会看到不是那么直接的比较特殊一点的宏定义,比如do{}while(0)。 do{conditional code}while(condition)结构 一般结构如以下代码 do { //循环体 } while (条件表达式); do wh

yinxiaohui0212的博客 280

C语言中do...while(0)的妙用

在linux内核代码中,经常看到do...while(0)的宏,do...while(0)有很多作用,下面举出几个: 1、避免goto语句: 通常,如果一个函数开始要分配一些资源,然后如果在中途遇到错误则要退出函数,当然,退出前要释放资源,我们的代码可能如下:  1 #defien N 10 2 3 bool Execute() 4 { 5 // 分配资源

u010031917的博客 7760

do/while(0)的妙用

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

Elric的专栏 1304

do while(0) 语句的妙用

在C++中,有三种类型的循环语句:for, while, 和do...while, 但是在一般应用中作循环时, 我们可能用for和while要多一些,do...while相对不受重视。但最近在读我们项目的代码时,却发现了do...while的一些十分聪明的用法,不是用来做循环,而是用作其他来提高代码的健壮性。 使用do{...}while(0)构造后的宏定义不会受到大括号、分号等的影响,总是会按...

有趣的人生 一半是山川湖海 一半是初心情怀 539
上一篇: GNU C中的零长度数组
下一篇: GNU C与ANSI C
ssdsafsdsd
博客等级 码龄15年 154粉丝 94原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值