在linux内核代码中,经常看到do...while(0)的宏,do...while(0)有很多作用,下面举出几个:

本文地址:http://www.cnblogs.com/archimedes/p/do-while-0.html,转载请注明源地址。

1、避免goto语句:

通常,如果一个函数开始要分配一些资源,然后如果在中途遇到错误则要退出函数,当然,退出前要释放资源,我们的代码可能如下: 

#defien N 

bool Execute()
{
// 分配资源
int *p = (int *)malloc(N * sizeof(int));
bool bOk = true; // 执行并进行错误处理
bOk = func1();
if(!bOk)
{
free(p);
p = NULL;
return false;
} bOk = func2();
if(!bOk)
{
free(p);
p = NULL;
return false;
} bOk = func3();
if(!bOk)
{
free(p);
p = NULL;
return false;
} // .......... // 执行成功,释放资源并返回
free(p);
p = NULL;
return true;
}

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

#defien N 

bool Execute()
{
// 分配资源
int *p = (int *)malloc(N * sizeof(int));
bool bOk = true; // 执行并进行错误处理
bOk = func1();
if(!bOk) goto errorhandle; bOk = func2();
if(!bOk) goto errorhandle; bOk = func3();
if(!bOk) goto errorhandle; // .......... // 执行成功,释放资源并返回
free(p);
p = NULL;
return true; errorhandle:
free(p);
p = NULL;
return false;
}

代码冗余是解决了,但是引入了C语言中比较微妙的goto语句,虽然正确的使用goto语句可以大大提高程序的灵活性与简洁性,但是会使我们的程序捉摸不定,为了既避免使用goto语句,又能消除代码冗余,可以考虑使用下面的 do...while(0):

#defien N 

bool Execute()
{
//分配资源
int *p = (int *)malloc(N * sizeof(int));
bool bOK = true; do {
//执行并进行错误处理
bOK = fun1();
if(!bOK) break; bOK = fun2();
if(!bOK) break; bOK = fun3();
if(!bOK) break; //.........
} while(); //释放资源 free(p);
p = NULL;
return bOK;
}

2、避免空声明在编译时出现警告:

在linux内核源代码中,经常看到如下宏以避免在编译时出现警告:

#define FOO do { } while(0)

3、编写符合习惯的代码块:

你可能经常会使用如下的宏:

#define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }

然而在某些情况下将会失效,下面的代码使用if...else...

if (x > y)
exch(x,y); // 分支 1
else
do_something(); // 分支 2

但是将被解释为一个分支的if语句:

if (x > y) {
int tmp;
tmp = x;
x = y;
y = tmp;
}
; // 空语句
else // ERROR!!!
do_something();

错误出在“;”直接位于代码块的后面,解决的办法是将代码嵌入do...while(0),于是得到下面的代码:

if (x > y)
do {
int tmp;
tmp = x;
x = y;
y = tmp;
} while();
else
do_something();

于是上面的宏可以修改为:

#define exch(x,y)       do {\
int tmp;\
tmp = x;\
x = y;\
y = tmp;\
} while()

4、在条件语句中使用复杂的宏:

假如一个宏包含类似如下几行代码:

#define FOO(x) \
printf("arg is %s\n", x); \
do_something_useful(x);

现在想像一下下面的代码:

if (blah == )
FOO(blah);

这将解释为:

if (blah == )
printf("arg is %s\n", blah);
do_something_useful(blah);;

我们就会发现,if语句只作用于printf(), do_something_useful() 没按照愿意一起执行,即没有像你预期的那样被包含在if代码中,于是可以使用如下的代码块:

if (blah == )
do {
printf("arg is %s\n", blah);
do_something_useful(blah);
} while ();

这样上面的宏就可以改为:

#define  FOO(x) do { \
printf("arg is %s\n", blah);\
do_something_useful(blah);\
} while ()

C语言中do...while(0)用法小结的更多相关文章

  1. C语言中system()函数的用法总结(转)

    system()函数功能强大,很多人用却对它的原理知之甚少先看linux版system函数的源码: #include <sys/types.h> #include <sys/wait ...

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

    转载来自:C语言中do...while(0)的妙用,感谢分享. 在linux内核代码中,经常看到do...while(0)的宏,do...while(0)有很多作用,下面举出几个: 1.避免goto语 ...

  3. C/C++语言中NULL、'\0’和0的区别

    注:本文参考了http://blog.csdn.net/mylinx/article/details/6873253及书籍<征服C指针>([日]前桥和弥著). NULL.'\0'和0的值是 ...

  4. C语言中static关键字的用法

    C记得还是大一时学的,现在觉得好久没用了,又捧起来看看.今天刚看到有关static关键字,仔细地看了一遍<C和指针>这本书中的解释,现在觉得清楚多了. 首先,我们将static关键字,修饰 ...

  5. C语言中的extern关键字用法

    在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”. 1. extern修饰变量的声明.举例来说,如果文件a.c需要引用b.c中变量int v ...

  6. C语言中sprintf()函数的用法

    sprintf函数的用法 1.该函数包含在stdio.h的头文件中. 2.sprintf和平时我们常用的printf函数的功能很相似.sprintf函数打印到字符串中,而printf函数打印输出到屏幕 ...

  7. C语言中strtod()函数的用法详解

    函数原型: #include <stdlib.h> double strtod(const char *nptr, char **endptr); C语言及C++中的重要函数. 名称含义 ...

  8. R语言中的logical(0)和numeric(0)以及赋值问题

    logical(0) 不等于 numeric(0).两者都不等于NULL值,即is.null(logical(0))和is.null(numeric(0))返还值都是FALSE.这很有意思,说明长度为 ...

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

    在linux内核代码中,经常看到do...while(0)的宏,do...while(0)有很多作用,下面举出几个: 1.避免goto语句: 通常,如果一个函数开始要分配一些资源,然后如果在中途遇到错 ...

随机推荐

  1. HTML5[8]: 图文混排,图片与文字居中对齐

    <img src="image.png"><span>999</span> img { /* ...  */ vertical-align: t ...

  2. JS文档和Demo自动化生成工具 - SmartDoc发布

    曾几何时,当你码神附体,一路披荆斩棘的完成代码后,带着“一码在手,天下我有”的傲然环顾之时,却发现单元测试.API文档.Demo实例陆续向你砸来,顿时有木有一种冰水挑战后的感觉.而这时你应该:哟哟,快 ...

  3. 关于js中的回收机制,通俗版

    在前面的几篇文章中,我讲解过了js中的回收机制,但是对于当时的我来说,我自己对回收机制的这个概念也有些懵懵懂懂,现在对回收机制有了更深入的理解,所以特此发布此文给于总结,也好加深记忆. 如果你想学习闭 ...

  4. codeforces Restore Cube(暴力枚举)

    /* 题意:给出立方体的每个顶点的坐标(是由源坐标三个数某几个数被交换之后得到的!), 问是否可以还原出一个立方体的坐标,注意这一句话: The numbers in the i-th output ...

  5. Android性能优化之内存篇

    下面是内存篇章的学习笔记,部分内容与前面的性能优化典范有重合,欢迎大家一起学习交流! 1)Memory, GC, and Performance 众所周知,与C/C++需要通过手动编码来申请以及释放内 ...

  6. How to implement an algorithm from a scientific paper

    Author: Emmanuel Goossaert 翻译 This article is a short guide to implementing an algorithm from a scie ...

  7. 15套漂亮的 PSD 格式的图标,不一样的视觉效果

    在 Web 设计领域,图标发挥非常重要的作用,因为美丽的和创造性的图标集可以很容易地使网页设计更有吸引力.网页设计设计师专注于每一个领域的设计,包括颜色选择.图标.创造力.混色等.正确的选择图标可以使 ...

  8. C#序列化JSON

    public static string ConvertToJsonString<T>(T instance) {             using (MemoryStream stre ...

  9. hive的内部表与外部表创建

    最近才接触Hive.学到了一些东西,就先记下来,免得以后忘了. 1.创建表的语句:Create [EXTERNAL] TABLE [IF NOT EXISTS] table_name [(col_na ...

  10. web面试题大全

    $HTML, HTTP,web综合问题 常见排序算法的时间复杂度,空间复杂度 前端需要注意哪些SEO web开发中会话跟踪的方法有哪些 <img>的title和alt有什么区别 docty ...