C语言中do...while(0)用法小结
在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)用法小结的更多相关文章
- C语言中system()函数的用法总结(转)
system()函数功能强大,很多人用却对它的原理知之甚少先看linux版system函数的源码: #include <sys/types.h> #include <sys/wait ...
- C语言中do...while(0)的妙用(转载)
转载来自:C语言中do...while(0)的妙用,感谢分享. 在linux内核代码中,经常看到do...while(0)的宏,do...while(0)有很多作用,下面举出几个: 1.避免goto语 ...
- C/C++语言中NULL、'\0’和0的区别
注:本文参考了http://blog.csdn.net/mylinx/article/details/6873253及书籍<征服C指针>([日]前桥和弥著). NULL.'\0'和0的值是 ...
- C语言中static关键字的用法
C记得还是大一时学的,现在觉得好久没用了,又捧起来看看.今天刚看到有关static关键字,仔细地看了一遍<C和指针>这本书中的解释,现在觉得清楚多了. 首先,我们将static关键字,修饰 ...
- C语言中的extern关键字用法
在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”. 1. extern修饰变量的声明.举例来说,如果文件a.c需要引用b.c中变量int v ...
- C语言中sprintf()函数的用法
sprintf函数的用法 1.该函数包含在stdio.h的头文件中. 2.sprintf和平时我们常用的printf函数的功能很相似.sprintf函数打印到字符串中,而printf函数打印输出到屏幕 ...
- C语言中strtod()函数的用法详解
函数原型: #include <stdlib.h> double strtod(const char *nptr, char **endptr); C语言及C++中的重要函数. 名称含义 ...
- R语言中的logical(0)和numeric(0)以及赋值问题
logical(0) 不等于 numeric(0).两者都不等于NULL值,即is.null(logical(0))和is.null(numeric(0))返还值都是FALSE.这很有意思,说明长度为 ...
- C语言中do...while(0)的妙用
在linux内核代码中,经常看到do...while(0)的宏,do...while(0)有很多作用,下面举出几个: 1.避免goto语句: 通常,如果一个函数开始要分配一些资源,然后如果在中途遇到错 ...
随机推荐
- js转html实体
方法一: 用的浏览器内部转换器实现转换,方法是动态创建一个容器标签元素,如DIV,将要转换的字符串设置为这个元素的innerText,然后返回这个元素的innerHTML,即得到经过HTML编码转换的 ...
- Linux高级编程--08.线程概述
线程 有的时候,我们需要在一个基础中同时运行多个控制流程.例如:一个图形界面的下载软件,在处理下载任务的同时,还必须响应界面的对任务的停止,删除等控制操作.这个时候就需要用到线程来实现并发操作. 和信 ...
- Android之TextView的Span样式源码剖析
Android中的TextView是个显示文字的的UI类,在现实中的需求中,文字有各式各样的样式,TextView本身没有属性去设置实现,我们可以通过Android提供的 Spannab ...
- 火狐浏览器修改userAgent
火狐浏览器修改userAgent的办法: 在火狐浏览器地址栏输入“about:config”,按下回车进入设置菜单. 找到“general.useragent.override”,如果没有这一项,则点 ...
- 一个python爬虫小程序
起因 深夜忽然想下载一点电子书来扩充一下kindle,就想起来python学得太浅,什么“装饰器”啊.“多线程”啊都没有学到. 想到廖雪峰大神的python教程很经典.很著名.就想找找有木有pdf版的 ...
- C#关键字
关键字 abstract as base bool break byte case catch char checked decimal default delegate continue doubl ...
- sphinx使用小记之使用小结
sphinx使用小记之使用小结 摘自:http://www.68idc.cn/help/jiabenmake/qita/20150124187789.html 在使用sphinx的过程中有出现一些问题 ...
- 【C#】第1章 VS2015中C#6的新特性
分类:C#.VS2015 创建日期:2016-06-12 一.简介 VS2015内置的C#版本为6.0,该版本提供了一些新的语法糖,这里仅列出个人感觉比较有用的几个新功能. 二.几个很有用的新特性 注 ...
- vs 2013各个版本密钥
Visual Studio Ultimate 2013 KEY(密钥):BWG7X-J98B3-W34RT-33B3R-JVYW9 Visual Studio Premium 2013 KEY(密钥) ...
- csharp: Flash Player play *.flv file in winform
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...