在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语句 不同类型数据的差异...
3. **控制结构**:包括顺序结构、选择结构(if...else, switch...case)和循环结构(for, while, do...while),它们控制程序的执行流程。 4. **函数**:函数是C语言的核心特性,可以将代码组织成可重用的模块。...
do...while循环是C语言中的一种循环结构,用于重复执行一段代码直到指定的条件不再满足为止。在do...while循环中,不管条件是否满足,循环体内的代码至少会被执行一次。这是与while循环不同之处,因为while循环可能...
2. **第03章**:通常会介绍控制流程语句,包括条件语句(if...else)和循环语句(for、while、do...while),这些都是编写逻辑程序的关键部分。 3. **第05章**:可能涵盖数组和指针,这是C语言的一大特色。学习者会...
3. **流程控制**:理解条件语句(if-else、switch-case)和循环结构(for、while、do-while)的使用,这些都是程序执行路径的重要组成部分。 4. **函数**:C语言中的函数是代码模块化的基础,学习如何定义、调用和...
控制结构是程序流程的骨架,包括顺序结构、选择结构(if...else语句、switch语句)和循环结构(for、while、do...while)。这些结构允许程序员根据条件执行不同的代码段或重复执行某些操作。 四、函数 函数是C语言...
1. 变量:C语言中的数据类型包括整型(int)、浮点型(float/double)、字符型(char)等,变量是存储数据的容器,需要先声明后使用。 2. 常量:常量是不可改变的值,分为整型常量、浮点型常量、字符常量和字符串...
接下来是流程控制,包括条件语句(if...else,switch...case)和循环语句(for,while,do...while)。这些结构使得程序可以根据不同条件执行不同的代码块,或重复执行某段代码直到满足特定条件为止。 函数是C语言...
2. **控制结构**:包括条件语句(if-else)、循环(for, while, do-while)和跳转语句(break, continue)。这些结构用于控制程序的流程,实现条件判断和重复执行。 3. **函数**:C语言中的函数是一组完成特定任务...
2. 控制语句:用于控制程序执行流程的语句,包括if条件语句、switch多分支选择语句、for循环语句、while循环语句以及do-while循环语句。 3. 函数:描述了如何通过函数来组织代码,实现代码的模块化。包括函数的声明...
控制结构是程序流程的基石,包括条件语句(if...else)、循环(for、while和do...while)以及跳转语句(break和continue)。这些章节会帮助读者学会如何根据条件执行不同的代码块,以及如何用循环实现重复任务。 ...
while循环在C语言中用于在满足特定条件时反复执行一段代码。其基本格式是: ```c while (条件表达式) { 语句集; } ``` 在示例中,我们看到一个简单的while循环例子,用于打印1到2的数字: ```c main() { int num =...
5. **流程控制语句**:包括顺序结构、选择结构(if-else)和循环结构(for、while、do-while),以及如何使用它们实现程序的逻辑控制。 6. **函数**:讨论函数的定义、调用、参数传递和返回值,以及函数的递归使用...
在C语言中,循环结构包括`for`循环、`while`循环以及`do...while`循环。例如,在文档中出现的`for(i=1;i;i+=2)sum+=i;`就是`for`循环的典型应用,用于遍历1到100之间的奇数并累加。又如`while(v){t=u%v;u=v;v=t;}`是...
2. **控制结构**:掌握if...else条件语句、switch选择结构、for、while、do...while循环语句的使用。 3. **函数**:理解函数的定义、调用,参数传递,以及函数指针的概念。 4. **数组**:包括一维数组、二维数组的...
3. **控制结构**:if...else语句、switch...case语句、for、while和do...while循环。 4. **函数**:定义函数、调用函数、函数参数传递和返回值。 5. **数组**:一维数组、二维数组及多维数组的声明、初始化和操作...
4. **控制结构**:条件语句(if...else、switch...case)和循环语句(for、while、do...while)用于控制程序的流程。 5. **函数**:函数的定义、调用、参数传递,以及函数指针的概念。 6. **数组**:一维数组、二...
2. 关键字和基本语法:文档中出现的“if”、“else”、“switch”、“while”、“do...while”、“for”等是C语言中常用的控制流语句关键字。这些关键字用于构建程序的逻辑结构,如条件判断和循环结构。 3. 算术...
最后,C语言具有结构化的控制语句,如if...else、while、do...while、switch、for等。 C语言的用途非常广泛,虽然不擅长科学计算和管理领域,但是对操作系统和系统实用程序以及对硬件进行操作方面,C语言有明显的...