经常在define语句中看到用do{} while(0)将一个程序片段包起来,一直感觉很奇怪,经查找,才发现这是在define语句使用中的一个tricky的情况。
define表达使用do{} while(0)的两个例子:
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
LIST_NEXT((listelm), field)->field.le_prev = \
&LIST_NEXT((elm), field); \
LIST_NEXT((listelm), field) = (elm); \
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
} while (0)
#define INIT_LIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
下面以第二个define语句为例子说明不使用do{}while(0)会用什么情况发生。
这是测试代码
#define INIT_LIST_HEAD(ptr) {(ptr)->next = (ptr); (ptr)->prev = (ptr);}
struct node {
struct node* next;
struct node* prev;
int val;
};
void main(){
struct node head;
if(1 == 0)
INIT_LIST_HEAD(&head);
else
head.val = 0;
}
预编译后的相关代码:
if(1 == 0)
{(&head)->next = (&head); (&head)->prev = (&head);};
else
head.val = 0;
然后编辑就会报错:main.c:13: error: ‘else’ without a previous ‘if’
相信看到这里后各位就会明白使用do{}while(0)的原因了吧。
分享到:
相关推荐
1. do…while(0)消除goto语句通常,如果在一个函数中开始要分配一些资源,然后在中途执行过程中如果遇到错误则退出函数,当然,退出前先释放资源,我们的代码可能是这样:version 1 代码如下:bool Execute(){ // ...
在这个例子中,`do-while`循环后的`printf`函数调用被错误地放置在了`while`语句的后面,没有与循环结构正确地隔离开。由于缺少分号,编译器会把`printf`视为`while`语句的一部分,从而报出`error C2146: syntax ...
在C++编程中,`do{...}while(0)`构造常常被用于宏定义和特殊控制结构中,尽管它在字面上看起来并不像一个常规的循环。以下详细解释了这一构造的意义和用法: 1. **辅助定义复杂的宏**: 当编写宏时,我们希望确保...
C语言是软件开发中最基础也是最重要的一部分,本文将对C语言中的常用语句进行总结,包括函数、基本语句、循环语句和其他语句等。 一、函数 1.putchar 函数:putchar 函数是一个字符输出函数,用于向终端输出一个...
"do {...} while (0)"结构在宏定义中的运用就是一种解决这些问题的技巧。 首先,让我们理解一下`do {...} while (0)`的基本原理。这个结构实际上创建了一个只有一个迭代的循环,但它的主要目的并不是进行真正的循环...
} while (0) /* (no trailing ;) */ ``` 在这个例子中,`MACRO` 宏接受两个参数 `arg1` 和 `arg2`,并在其定义体内执行一系列语句。 #### 4. 条件编译 `#define` 在C语言中的另一个重要用途是条件编译。通过在源...
do...while(0)结构在C++编程中常常被用于消除`goto`语句的使用,从而提高代码的可读性和可维护性。在传统的错误处理模式中,当需要在函数内部分配资源并在遇到错误时释放这些资源时,通常会看到类似这样的代码,即...
define 可以替代多行的代码,在每一个换行的时候加上一个"\",例如 #define MAX(X,Y) do { 语句 1; 语句 2; /* 注释的写法 */ } while(0)。 5. 条件编译 define 的多行定义可以让我们在编译的时候通过#define 设置...
} while(0) /* (no trailing ; ) */ ``` 在每一行末尾使用反斜杠`\`继续下一行,可以实现多行效果。 5. **条件编译** `#ifdef`, `#ifndef`, `#else`, `#endif`这些条件编译指令允许根据宏定义的状态选择性地...
循环语句用于重复执行某个语句块,包括while语句、do-while语句和for语句。 * while语句:`while (条件) 语句` * do-while语句:`do 语句 while (条件)` * for语句:`for (exp1;exp2;exp3) 语句` 转移语句 转移...
- 循环语句:for,while,do...while。 - 分支语句:break,continue,return。 5. **数组**:用于存储同类型数据的集合,如“int numbers[5];”声明一个包含5个整数的数组。 6. **指针**:C语言的重要特性,...
PIC单片机C语言程序设计中循环语句是十分关键的部分,包括for循环和do-while循环,这些语句在执行中实现程序的迭代和重复,对于实现延时功能和控制程序流程非常有用。 ##### 2.1 for循环 for循环语句的一般形式为...
这个宏定义了一个结构体,使用了do-while循环,以确保即使语句块只包含一条语句,也使用大括号包围起来。 8. 宏与其他预处理指令混合使用 有时候宏定义可能会和预处理指令如#ifdef、#else、#endif混合使用。 ```c #...
do-while循环的执行过程是:首先执行循环体中的语句,然后计算条件表达式的值,如果其值为真,则继续执行循环体中的语句,直到其值为假为止。 例如,下面是一个简单的do-while循环的示例: ```c int i = 1; int sum...
* for 语句、while 语句和 do-while 语句是 C 语言中的循环类语句。 * for 语句用于执行指定次数的循环操作。 * while 语句用于执行条件满足的循环操作。 * do-while 语句用于执行条件满足的循环操作。 四、输入...
* do-while循环的格式为:do 语句 while(条件); 十、数组: * 在C语言中,数组是指一组相同类型的元素的集合。 * 数组的声明格式为:数据类型 数组名[大小]; * 数组的元素可以是整数、实数、字符或字符串。 * 数组...
`do...while` 循环语句中必须包含 `while` 子句。 **解决方法:** - 确保 `do...while` 语句结构完整。 - 添加缺失的 `while` 子句。 #### 33. Do-while statement missing '(' (do-while 语句缺少 '(') 如果 `do...
* do...while 循环语句:do{ 循环语句 } while(循环条件); * for 循环语句:for(起始表达式;条件表达式;末尾循环体) { 循环语句; } 十三、函数 C++中的函数用于封装代码,提高代码的可重用性和可读性。 * 函数的...
因此,在工程中,一般使用三种方式来对函数宏进行封装,分别为 {}、do{...}while(0) 和 ({})。下文将一一对三种方式进行分析,比较各自的优劣点。 2. {} 方式 INT_SWAP 宏使用 {} 封装后形态如下: 复制 #define...