C++ do{...}while(0)的好处

在开源软件里面经常可以看到这样的写法。

#define X(a) do { f1(a); f2(a); } while(0)

1. 主要作用是放在宏定义里面,避免宏带来的语法问题。

比如

#define DOSOMETHING()               cmd1;               cmd2;

而调用的时候
if(a>0)
    DOSOMETHING(); 会有问题,需要用到上面提到的

而这时候,为什么不用 if (1) { ... } 呢?

有两方面原因:首先,会多出不必要的分号,比如:
if (1)
    my_code;

另外更重要的是,有if-else的问题:
if (1)
    my_code;
else { ... }

当然了,如果定义成 
#define X(a) if(1) { f1(a); f2(a); } else{}

就和下面的 do...while(0)一样安全了。但是上面的if-else写法不需要写分号;,有利有弊。
#define X(a) do { f1(a); f2(a); } while(0)

2. 还有一个重要原因是,可以用来取代goto跳转。

比如下面带goto的代码:

int foo()
{
    somestruct* ptr = malloc(...);

    dosomething...;
    if(error)
    {
        goto END;
    }

    dosomething...;
    if(error)
    {
        goto END;
    }
    dosomething...;

END:
    free(ptr);
    return 0;

}

可以利用do...while(0)和break的配合,写成:

int foo()
{

    somestruct* ptr = malloc(...);

    do{
        dosomething...;
        if(error)
        {
            break;
        }

        dosomething...;
        if(error)
        {
            break;
        }
        dosomething...;
    }while(0);

    free(ptr);
    return 0;

}

goto转换为do...while+break,在程序结构上、编译优化上,都有很多好处。我觉得。

3、避免空宏引起的warning

内核中由于不同架构的限制,很多时候会用到空宏,在编译的时候,空宏会给出warning,为了避免这样的warning,就可以使用do{}while(0)来定义空宏:

#define EMPTYMICRO do{}while(0)

我觉得,这个也可以用if-else来代替。

4、定义一个单独的函数块来实现复杂的操作,避免作用域或者命名空间冲突

当你的功能很复杂,变量很多你又不愿意增加一个函数的时候,使用do{}while(0);,将你的代码写在里面,里面可以定义变量而不用考虑变量名会同函数之前或者之后的重复。

(完)

时间: 2024-10-05 16:17:22

C++ do{...}while(0)的好处的相关文章

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

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

函数式宏定义用do...while(0)的好处

函数式宏定义经常写成这样:<pre lang="c" escaped="true">#define device_init_wakeup(dev, val) \ do { \ device_can_wakeup(dev) = !!(val); \ device_set_wakeup_enable(dev, val); \ }while(0) </pre> 为什么要用do {...} while(0) 括起来呢?不括起来会有什么问题呢?

HTTP2.0那些事

1. HTTP2.0的前世 http2.0的前世是http1.0和http1.1这两兄弟.虽然之前仅仅只有两个版本,但这两个版本所包含的协议规范之庞大,足以让任何一个有经验的工程师为之头疼.http1.0诞生于1996年,协议文档足足60页.之后第三年,http1.1也随之出生,协议文档膨胀到了176页.不过和我们手机端app升级不同的是,网络协议新版本并不会马上取代旧版本.实际上,1.0和1.1在之后很长的一段时间内一直并存,这是由于网络基础设施更新缓慢所决定的.今天的http2.0也是一样,

HTTP 2.0的那些事

转自:http://www.admin10000.com/document/9310.html 在我们所处的互联网世界中,HTTP协议算得上是使用最广泛的网络协议.最近http2.0的诞生使得它再次互联网技术圈关注的焦点.任何事物的消退和新生都有其背后推动的力量.对于HTTP来说,这力量复杂来说是各种技术细节的演进,简单来说是用户体验和感知的进化.用户总是希望网络上的信息能尽可能快的抵达眼球,越快越好,正是这种对“快”对追逐催生了今天的http2.0. 1. HTTP2.0的前世 http2.0

Android学习之友盟5.0推送,分享踩坑总结

这几天都没有写博客,今天集成友盟5.0推送,分享,得闲,总结一下友盟5.0推送分享踩得哪些坑! 之前写的友盟踩坑心得是基于友盟4.3版本的,现在友盟5.0相较于4.3,有了较大的改动,呜呼哀哉!学而时习之吧. 友盟5.0的好处:集成推送,分享可以通过导入module的形式,代码简化,维护性高,(一些资源文件就不用自己慢慢去拷贝了). 至于缺点,就是刚刚改版,会有很多跟4.3不一样的使用方法,所以需要前人去踩坑了! 友盟推送: 1:添加Module Android studio导入Module自不

thinkphp5.0数据库备份

首页说一下tp5.0的好处就是可以使用composer安装数据库备份类库,composer命令安装:composer require tp5er/tp5-databackup dev-master安装成功后会在项目文件夹vendor下自动生成数据库备份类库:以上步骤操作完成开始使用:1.新建个控制器,在控制器中建备份方法,想使用数据库备份类,就先use \tp5er\Backup;2.基本配置信息,默认传入下面参数$config=array('path' => './Data/',//数据库备份

宏------进阶

宏定义的黑魔法 - 宏菜鸟起飞手册 宏定义在C系开发中可以说占有举足轻重的作用.底层框架自不必说,为了编译优化和方便,以及跨平台能力,宏被大量使用,可以说底层开发离开define将寸步难行.而在更高层级进行开发时,我们会将更多的重心放在业务逻辑上,似乎对宏的使用和依赖并不多.但是使用宏定义的好处是不言自明的,在节省工作量的同时,代码可读性大大增加.如果想成为一个能写出漂亮优雅代码的开发者,宏定义绝对是必不可少的技能(虽然宏本身可能并不漂亮优雅XD).但是因为宏定义对于很多人来说,并不像业务逻辑那

宏!!!!(拷贝别人的博客的只为了收藏)

入门 如果您完全不知道宏是什么的话,可以先来热个身.很多人在介绍宏的时候会说,宏嘛很简单,就是简单的查找替换嘛.嗯,只说对了的一半.C中的宏分为两类,对象宏(object-like macro)和函数宏(function-like macro).对于对象宏来说确实相对简单,但却也不是那么简单的查找替换.对象宏一般用来定义一些常数,举个例子: //This defines PI #define M_PI 3.14159265358979323846264338327950288 #define关键

宏定义的黑魔法 - 宏菜鸟起飞手册

转载:https://onevcat.com/2014/01/black-magic-in-macro/ 宏定义在C系开发中可以说占有举足轻重的作用.底层框架自不必说,为了编译优化和方便,以及跨平台能力,宏被大量使用,可以说底层开发离开define将寸步难行.而在更高层级进行开发时,我们会将更多的重心放在业务逻辑上,似乎对宏的使用和依赖并不多.但是使用宏定义的好处是不言自明的,在节省工作量的同时,代码可读性大大增加.如果想成为一个能写出漂亮优雅代码的开发者,宏定义绝对是必不可少的技能(虽然宏本身