在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)
文章来源:http://www.itnose.net/detail/6024252.html
更多文章:http://www.itnose.net/type/54.html
相关推荐
- **3.5.4 字符数据在内存中的存储形式及使用方法:** 字符数据以ASCII码的形式存储。 - **3.5.5 字符串常量:** 由一对双引号括起来的字符序列。 - **3.5.6 符号常量:** 通过`#define`预处理指令定义。 - **3.6...
2.6.7 关于优先级的小结 27 2.7 表达式 28 2.7.1 表达式中的类型转换 28 2.7.2 构成符cast 29 2.7.3 空格与括号 29 2.7.4 C语言中的简写形式 29 第3章 程序控制语句 31 3.1 程序的三种基本结构 31 3.2 数据的输入与...
3.5.4 字符数据在内存中的存储形式及使用方法... 10 3.5.5 字符串常量... 11 3.5.6 符号常量... 12 3.6 变量赋初值... 12 3.7 各类数值型数据之间的混合运算... 13 3.8 算术运算符和算术表达式... 14 3.8.1 C...
### C语言常见错误小结 #### 一、变量声明与使用不一致 在代码示例中,出现了变量声明与实际使用时不一致的情况: ```c main() { int a = 5; printf("%d", A); } ``` 这里的问题在于`printf`函数中的`A`未被...
### C语言常见易错点小结 C语言作为一种强大的编程语言,在软件开发领域有着广泛的应用。然而,由于其编译器对于语法的检查不如其他一些高级语言那样严格,因此在编写过程中很容易出现一些不易察觉的错误。对于初学...
- **3.5.4 字符数据在内存中的存储形式及使用方法** - **3.5.5 字符串常量** - **3.5.6 符号常量** **3.6 变量赋初值** - 在声明变量时可以为其赋初值。 **3.7 各类数值型数据之间的混合运算** - 不同类型的数据...
### C语言常见错误小结 C语言是一种功能强大且使用灵活的编程语言。然而,它的灵活性也带来了一定的学习曲线,尤其是对于初学者而言。本文将详细介绍C语言中常见的错误,帮助读者避免这些陷阱。 #### 1. 大小写...
这本电子教案不仅包含了完整的课程内容,还特别加入了C语言学习过程中常见错误的小结,使得学习过程更为高效且有针对性。 C语言是一种基础且强大的编程语言,它以其简洁、高效和灵活性闻名。在本教程中,你将了解到...
18.3.8 存储类别小结 199 18.4 编译预处理 201 18.4.1 宏替换 201 18.4.2 文件包括 204 18.4.3 条件编译(选讲内容) 204 18.5 如何运行一个多文件的程序 207 习题 208 第19章 C++对C的扩充 211 19.1 C++的...
6.3 while语句:详细描述了while循环的结构和使用方法。 6.4 do-while语句:讲解了do-while循环的结构特点和使用场景。 6.5 for语句:解释了for循环的格式和使用技巧。 6.6 循环的嵌套:讨论了如何在一个循环内部...
**实验目标**:掌握循环结构`while`、`do...while`、`for`语句的使用方法。 **实验内容**: - **需求说明**:使用三种不同的循环结构计算100以内所有正整数的加和。 - **程序设计**: 1. 使用`while`循环计算。 2...
3.5.4 字符数据在内存中的存储形式及使用方法 41 3.5.5 字符串常量 41 3.5.6 符号常量 42 3.6 变量赋初值 42 3.7 各类数值型数据之间的混合运算 43 3.8 算术运算符和算术表达式 44 3.8.1 C运算符简介 44...
##### 2.4 C语言中的句子小结 - 在C语言中,语句以分号`;`结尾。每个语句都有其特定的功能,如变量声明、函数调用、控制流等。 ##### 2.5 用C语言写一段话——程序段 - 程序段是一系列语句的组合,用于完成特定的...
本实验报告主要介绍了循环结构的设计方法和实现技术,包括while、for、do while语句的使用方法,以及循环结构和选择结构的嵌套设计方法。同时,也讨论了break、continue、goto语句的使用方法。 一、实验目的和要求 ...
(六)课程小结 本节课主要学习了循环结构中的for循环语句。学习对for循环条件、循环变量的设置,以避免无限循环的产生。能过使用for循环结构解决问题。 (七)布置作业 1. 求 100以内偶数之和。 2. 求 100以内 3...
18. **输入输出**:当输入55566 7777abc,`y`的值为7777.0,因为`scanf`会忽略空格,只读取到第一个非空字符。选项C正确。 19. **do...while循环**:循环结束后,`i`自增变为1,所以输出结果是1。选项B正确。 20. ...
2.6.7 关于优先级的小结 27 2.7 表达式 28 2.7.1 表达式中的类型转换 28 2.7.2 构成符cast 29 2.7.3 空格与括号 29 2.7.4 C语言中的简写形式 29 第3章 程序控制语句 31 3.1 程序的三种基本结构 31 3.2 数据的输入与...