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

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

1、避免goto语句:

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

#defien N 10bool 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;
}

View Code

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

#defien N 10bool 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;
}

View Code

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

#defien N 10bool 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(0);//释放资源
    free(p);p = NULL;return bOK;
}

View Code

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(0);
elsedo_something();

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

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

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

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

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

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

if (blah == 2)FOO(blah);

这将解释为:

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

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

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

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

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

C语言中do...while(0)用法小结相关推荐

  1. scanf在c语言中的作用,c语言中scanf的基本用法

    前言 scanf()是C语言的格式输入函数,和printf函数一样被声明在stdio.h头文件中,它的基本使用很简单: 1 int a; 2 scanf("%d",&a); ...

  2. c语言中 char怎样用,C语言中char*和char[]用法区别分析

    C语言中char*和char[]用法区别分析 本文实例分析了C语言中char* 和 char []的区别.分享给大家供大家参考之用.具体分析如下: 一般来说,很多人会觉得这两个定义效果一样,其实差别很 ...

  3. C语言中atoi()函数的用法

    C语言中atoi()函数的用法 一.学习要点: 1.int atoi(const char *str)把参数str所指向的字符串转换为一个整数: 二.代码 #include<stdio.h> ...

  4. python语言中with as的用法使用详解

    本篇文章主要介绍了python语言中with as的用法使用详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 With语句是什么? 有一些任务,可能事先需要设置,事后做 ...

  5. c语言memcopy_C语言中memcpy 函数的用法详解

    C语言中memcpy 函数的用法详解 memcpy(内存拷贝函数) c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址 ...

  6. c语言time函数的作用,c语言中time函数的用法

    c语言中time函数的用法 c语言中time函数的用法的用法你知道吗?下面应届毕业生小编就跟你们详细介绍下c语言中time函数的用法的用法,希望对你们有用. c语言中time函数的用法的用法如下: 头 ...

  7. c语言sinx的作用,C语言中 sinx cosx 的用法

    #include #include int main() { double pi=acos(-1.0); double angle; scanf("%lf",&angle) ...

  8. div c语言,c语言中的div的用法是什么?

    c语言中的div的用法: 函数名: div 功 能: 将两个整数相除, 返回商和余数 用 法: div_t (int number, int denom); 程序例: # include #inclu ...

  9. 在c语言中for的作用,c语言中for语句的用法

    C语言语言中FOR的用法 for 是一个循环语句,和while是类似的,for一般的用法有: for(i=0;i<10;i++) { printf("hello world" ...

最新文章

  1. 学习webpack记录(一)
  2. Notepad++V6.8.1.0中文版
  3. 深入浅出Mybatis系列(八)---mapper映射文件配置之select、resultMap good
  4. Shell脚步学习指南提点
  5. PHP $_SERVER详解
  6. 机器学习第五回——学习方法与学习曲线
  7. Ubuntu终端快捷复制粘贴
  8. .net core mvc中使用ef
  9. Base64 混淆加密+迭代次数,Base64前后端加解密不一致、Base64 js加解密结果与java加解密结果不一致,Base64中文加密乱码
  10. 语音识别入门第七节:语言模型
  11. KISSY基础篇乄KISSY之IO(1)
  12. Spark Scala当中reduceByKey(_+_) reduceByKey((x,y) => x+y)的用法
  13. 分享些发表技术类文章的平台
  14. #1082 : 然而沼跃鱼早就看穿了一切
  15. Android Adapter接口的实现类总结
  16. js替换关键词为链接,只替换一次,要避开超链接或图片
  17. vscode json文件配置
  18. 复旦大学游记(r10笔记第88天)
  19. Netty的UDP广播发送与接收
  20. 线性代数 or 量子力学 ? (外传:傅里叶级数 与 傅里叶变换学习笔记)

热门文章

  1. python能做什么游戏好-用Python可以做哪些有意思的小游戏呢?
  2. 在linux上安装Filezilla文件传输FTP软件
  3. UVa512 - Spreadsheet Tracking
  4. Qt运行一个实例进程
  5. elasticsearch入门一
  6. linux-压缩与解压缩(gz,zip,tar,jar,war)
  7. Excel一对多查找
  8. 9.Methods(二)
  9. C#让两个长度相同的数组一一对应
  10. 去除字符串标点 + 泛型算法使用