在linux内核代码中,经常看到do...while(0)的宏,do...while(0)有很多作用,下面举出几个:
1、避免goto语句:
通常,如果一个函数开始要分配一些资源,然后如果在中途遇到错误则要退出函数,当然,退出前要释放资源,我们的代码可能如下:
#defien N 10 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 10 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 10 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(0); //释放资源 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(0); else do_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)
PS:以上的第三种和第四种技巧,并不是唯一的方法,有同学可能会说用其他的方法也可以实现,反而显得这样的宏定义过于花哨?事实并非如此,这样的宏定义在linux内核代码中非常常见,原因是代码简洁、通用、可移植性好
相关推荐
51单片机-C语言for语句do...while语句if...else...语句产生随机数rand()常用基本语句例程源码 do...while语句 for语句 if...else...语句 switch-case-break语句 while与do...while区别 while语句 不同类型数据的差异...
27. do/while(0)的妙用 134 28. exit()和return()的区别 140 29. exit子程序终止函数与return的差别 141 30. extern与static存储空间矛盾 145 31. PC-Lint与C\C++代码质量 147 32. spirntf函数使用大全 158 33. ...
今天咱们学习一下do......while的用法,快来学学吧。
do/while(0)的妙用 ....................................................................................................................... 120 28. exit()和return()的区别 .................................
C语言实现求1+2+3+……+100的和,要求分别用while、do while、for循环实现。.txt
1.8,do、while、for 关键字................................................................................................... 28 1.8.1,break 与continue 的区别............................................
下面列出ANSI标准定义的32个C语言的关键字,这些关键字在以后的学习中基本上都会用到,到时再说它们的各自用法。 auto break case char const continue default do double else enum extern float for goto if int ...
for、while、do while等循环结构语句的使用注意事项和易错点解析; 循环结构中break、continue、goto、return、exit的区别; 一维数组、二维数组、多维数组、字符数组、动态数组的定义和引用,以及操作数...
290-用do-while语句控制P0口8位LED流水点亮单片机C语言源码.zip项目程序C语言源码下载290-用do-while语句控制P0口8位LED流水点亮单片机C语言源码.zip项目程序C语言源码下载 1.合个人学习技术做项目参考 2.适合学生做...
2.7.4 C语言中的简写形式 29 第3章 程序控制语句 31 3.1 程序的三种基本结构 31 3.2 数据的输入与输出 31 3.2.1 scanf()函数 31 3.2.2 printf()函数 33 3.2.3 getchar()函数与putchar()函数 36 3.2.4 程序...
2.3.6. do-while..............................................................................................................25 2.3.7. goto-label-if.......................................................
27. do/while(0)的妙用 134 28. exit()和return()的区别 140 29. exit子程序终止函数与return的差别 141 30. extern与static存储空间矛盾 145 31. PC-Lint与C\C++代码质量 147 32. spirntf函数使用大全 158 33. ...
if、for、do、while、case、switch、default等语句自占一行,且if、for、do、while等语句的执行语句部分无论多少都要加括号{};程序块的分界符(大括号‘{’和‘}’)应各独占一行并且位于同一列,同时与引用它们的...
27. do/while(0)的妙用 134 28. exit()和return()的区别 140 29. exit子程序终止函数与return的差别 141 30. extern与static存储空间矛盾 145 31. PC-Lint与C\C++代码质量 147 32. spirntf函数使用大全 158 33...
C语言23:用do-while语句控制P0口8位LED流水点亮
但在do-while语句中,若while后面的表达式一开始就为假时,则先执行循环体,然后转向循环体下面的语句执行,这与while循环是不同的。 do-while语句的表达式后面必须加分号。 3 do-while语句 【例5.5】编写计算s=1+2+...
290-用do-while语句控制P0口8位LED流水点亮(51单片机C语言实例Proteus仿真和代码)290-用do-while语句控制P0口8位LED流水点亮(51单片机C语言实例Proteus仿真和代码)290-用do-while语句控制P0口8位LED流水点亮(51...
(4)掌握实现循环结构的三种语句while、 do-while.、for 的使用。 (5)掌握函数的定义方法和调用方法。 (6)能够采用模块化思想调试程序。 3. 课题分析: 对一个有N个学生的班级,每个学生有M门课程。该系统实现对班级...
C语言程序设计-用do-while语句求1~100的累计和;.c
C语言编程技术实践 while和do while语句教学单元设计.doc 学习资料 复习资料 教学资源