linux内核和其他一些开源的代码中,经常会遇到这样的代码:

do{
...
}while()

这样的代码一看就不是一个循环,do..while表面上在这里一点意义都没有,那么为什么要这么用呢?

实际上,do{...}while(0)的作用远大于美化你的代码。查了些资料,总结起来这样写主要有以下几点好处:

1、辅助定义复杂的宏,避免引用的时候出错:

举例来说,假设你需要定义这样一个宏:

#define DOSOMETHING()\
foo1();\
foo2();

这个宏的本意是,当调用DOSOMETHING()时,函数foo1()和foo2()都会被调用。但是如果你在调用的时候这么写:

if(a>)
DOSOMETHING();

因为宏在预处理的时候会直接被展开,你实际上写的代码是这个样子的:

if(a>)
foo1();
foo2();

这就出现了问题,因为无论a是否大于0,foo2()都会被执行,导致程序出错。

那么仅仅使用{}将foo1()和foo2()包起来行么?

我们在写代码的时候都习惯在语句右面加上分号,如果在宏中使用{},代码里就相当于这样写了:“{...};”,展开后就是这个样子:

if(a>)
{
foo1();
foo2();
};

这样甚至不会编译通过。所以,很多人才采用了do{...}while(0);

#define DOSOMETHING() \
do{ \
foo1();\
foo2();\
}while()\ ... if(a>)
DOSOMETHING(); ...

这样,宏被展开后,才会保留初始的语义。GCC提供了Statement-Expressions用以替代do{...}while(0); 所以你也可以这样定义宏:

#define DOSOMETHING() ({\
foo1(); \
foo2(); \
})

2、避免使用goto对程序流进行统一的控制:

有些函数中,在函数return之前我们经常会进行一些收尾的工作,比如free掉一块函数开始malloc的内存,goto一直都是一个比较简便的方法:

int foo()
{
somestruct* ptr = malloc(...); dosomething...;
if(error)
{
goto END;
} dosomething...;
if(error)
{
goto END;
}
dosomething...; END:
free(ptr);
return ; }

由于goto不符合软件工程的结构化,而且有可能使得代码难懂,所以很多人都不倡导使用,那这个时候就可以用do{}while(0)来进行统一的管理:

int foo()
{ somestruct* ptr = malloc(...); do{
dosomething...;
if(error)
{
break;
} dosomething...;
if(error)
{
break;
}
dosomething...;
}while(); free(ptr);
return ; }

这里将函数主体使用do()while(0)包含起来,使用break来代替goto,后续的处理工作在while之后,就能够达到同样的效果。

3、避免空宏引起的warning

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

#define EMPTYMICRO do{}while(0)

4、定义一个单独的函数块来实现复杂的操作:

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

do{...}while(0)的意义和用法的更多相关文章

  1. do{...}while(0)的意义和用法(转载)

    linux内核和其他一些开源的代码中,经常会遇到这样的代码: do{ ... }while(0) 这样的代码一看就不是一个循环,do..while表面上在这里一点意义都没有,那么为什么要这么用呢? 实 ...

  2. duilib各种布局的作用,相对布局与绝对布局的的意义与用法

    大多数刚使用duilib的朋友时候非常依赖duilib自带的设计器,用他可以拖拉控件,可视化的做出自己想要的界面.可是用一段时间就会发现原带的设计器有很多bug,时不时会崩溃,支持的控件数量有限,属性 ...

  3. 【转】Thread.sleep(0)的意义

    Thread.sleep(0)的意义 2012-03-23 17:47 2188人阅读 评论(2) 收藏 举报 windows算法unixthread 我们可能经常会用到 Thread.Sleep 函 ...

  4. 详解C++中命名空间的意义和用法

    看过鸡啄米的C++编程入门系列教程的朋友,应该能注意到,在其中的很多实例中,都有这么一条语句:using namespace std;,即使用命名空间std,其作用就是规定该文件中使用的标准库函数都是 ...

  5. EOF的意义及用法

    c/c++ 中EOF的意义及用法 EOF,为End Of File的缩写,通常在文本的最后存在此字符表示资料结束. 在微软的DOS和Windows中,读取数据时终端不会产生EOF.此时,应用程序知道数 ...

  6. java中异常(Exception)的定义,意义和用法。举例

    1.异常(Exception)的定义,意义和用法 我们先给出一个例子,看看异常有什么用? 例:1.1- public class Test {    public static void main(S ...

  7. jni中arm64-v8a,armeabi-v7a,armeabi文件夹的意义和用法<转>

    jni中arm64-v8a,armeabi-v7a,armeabi文件夹的意义和用法 起因 之前并没有关注这块,直到:您的应用被拒绝,原因:xplay5sQ心里点击笑值点击拍照显示停止运行,查看发过来 ...

  8. [转]0.python:scikit-learn基本用法

    感谢百小度治哥,该文原地址:here 经Edwin Chen的推荐,认识了scikit-learn这个非常强大的python机器学习工具包.这个帖子作为笔记.(其实都没有笔记的意义,因为他家文档做的太 ...

  9. 发现linux shell中$0,$?,$!等的特殊用法

    记录下linux shell下的特殊用法及参数的说明 变量说明: $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $? 最后运行的命令的结束代 ...

随机推荐

  1. Tomcat编码问题及访问软链接文件设置

    Tomcat编码问题及访问软链接文件设置 一.编码问题:让其支持UTF-8格式 修改tomcat中server.xml Connector port=" protocol="org ...

  2. servlet生命周期与工作原理

    →   Jsp的本质是Servlet,Servlet是服务器端的小程序,运行在服务器,用于处理及响应客户端的请求. Servlet和JSP的区别: servlet是特殊的Java类,必须继承HttpS ...

  3. js的元素对象

    元素对象(element对象)        ** 要操作element对象,首先必须要获取到element,                       - 使用document里面相应的方法获取  ...

  4. ng-repeat指令使用详解

    ng-repeat指令使用详解 link: function(scope,element,attr) scope.$index: if(scope.$last == true){} attr['mng ...

  5. app的meta

    <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> < ...

  6. 用一个简单的例子来理解python高阶函数

    ============================ 用一个简单的例子来理解python高阶函数 ============================ 最近在用mailx发送邮件, 写法大致如 ...

  7. uva10870 递推关系Recurrences

    Consider recurrent functions of the following form:f(n) = a1f(n - 1) + a2f(n - 2) + a3f(n - 3) + : : ...

  8. 必须知道的.net(继承)

    1.继承定义:就是面向对象中类与类之间的一种关系.通过继承,使得子类具有父类的属性和方法,同时子类也可以通过加入新的属性和方法或者修改父类的属性和方法建立新的类层次. 2.CLR支持实现单继承和接口多 ...

  9. 调用WebService 实现在线双向翻译

    >先了解一下Web Service的基本概念: Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传 ...

  10. POJ 2115 C Looooops

    扩展GCD...一定要(1L<<k),不然k=31是会出错的 ....                        C Looooops Time Limit: 1000MS   Mem ...