do while(0)的作用以及原因

简介: do while(0)的作用以及原因

在C++中,do...while 通常是用来做循环用的,然而我们做循环操作可能用for和while要多一些。经常看到一些开源代码会出现do...while(0)这样的代码,这样的代码看上去肯定不是用来做循环的,那为什么要这样用呢?

实际上do...while(0)的作用远大于美化代码,现总结起来主要有以下几个作用:

辅助定义复杂的宏,避免引用的时候出错,提高代码健壮性

假设你需要定义一个这样的宏:

1. #define DOSOMETHING()\
2. 
3. func1();\
4. 
5. func2();

这个宏的本意是,当调用DOSOMETHING()时,函数func1()和func2()都会被调用。但是如果你在调用的时候这么写:

1. if(a>0)
2. DOSOMETHING();

因为宏在预处理的时候会直接被展开,你实际上写的代码是这个样子的:

1. if(a>0)
2. 
3. func1();
4. 
5. func2();

这就出现了问题,因为无论a是否大于0,func2()都会被执行,导致程序出错。

那么仅仅使用{}将func1()和func2()包起来行么?

我们在写代码的时候都习惯在语句右面加上分号,如果在宏中使用{},代码里就相当于这样写了:“{...};”,假如有以下代码:

1. #define DOSOMETHING(){\
2. 
3. func1();\
4. 
5. func2();}
6. ...
7. if(a>0)
8. DOSOMETHING();
9. else
10.    ...
11. ...

展开后就是这个样子:

1. if(a>0)
2. {
3. func1();
4. 
5. func2();
6. };
7. else
8.     ...

这样是不会编译通过。所以,很多人才采用了do{...}while(0);

1. #define DOSOMETHING() \
2. 
3.         do{ \
4. 
5. func1();\
6. 
7. func2();\
8. 
9.         }while(0)\
10. 
11. ...
12. if(a>0)
13. DOSOMETHING();
14. else
15.     ...
16. ...

消除分支语句或者goto语句,提高代码的易读性

如果在一个函数中开始要分配一些资源,然后在中途执行过程中如果遇到错误则退出函数,当然,退出前先释放资源,我们的代码可能是这样:

1. bool Execute()
2. {
3. // 分配资源
4.    int *p = new int;
5.    bool bOk(true);
6. 
7. // 执行并进行错误处理
8.    bOk = func1();
9. if(!bOk) 
10.    {
11. delete p;   
12.       p = NULL;
13. return false;
14.    }
15. 
16.    bOk = func2();
17. if(!bOk) 
18.    {
19. delete p;   
20.       p = NULL;
21. return false;
22.    }
23. 
24.    bOk = func3();
25. if(!bOk) 
26.    {
27. delete p;   
28.       p = NULL;
29. return false;
30.    }
31. 
32. // ..........
33. 
34. // 执行成功,释放资源并返回
35. delete p;   
36.     p = NULL;
37. return true;
38. 
39. }

这里一个最大的问题就是代码的冗余,而且我每增加一个操作,就需要做相应的错误处理,非常不灵活。于是我们想到了goto:

1. bool Execute()
2. {
3. // 分配资源
4.    int *p = new int;
5.    bool bOk(true);
6. 
7. // 执行并进行错误处理
8.    bOk = func1();
9. if(!bOk) goto errorhandle;
10. 
11.    bOk = func2();
12. if(!bOk) goto errorhandle;
13. 
14.    bOk = func3();
15. if(!bOk) goto errorhandle;
16. 
17. // ..........
18. 
19. // 执行成功,释放资源并返回
20. delete p;   
21.     p = NULL;
22. return true;
23. 
24. errorhandle:
25. delete p;   
26.     p = NULL;
27. return false;
28. 
29. }

代码冗余是消除了,但是我们引入了C++中身份比较微妙的goto语句,虽然正确的使用goto可以大大提高程序的灵活性与简洁性,但太灵活的东西往往是很危险的,它会让我们的程序捉摸不定,那么怎么才能避免使用goto语句,又能消除代码冗余呢,请看do...while(0)循环:

1. bool Execute()
2. {
3. // 分配资源
4.    int *p = new int;
5. 
6.    bool bOk(true);
7.    do
8.    {
9. // 执行并进行错误处理
10.       bOk = func1();
11. if(!bOk) break;
12. 
13.       bOk = func2();
14. if(!bOk) break;
15. 
16.       bOk = func3();
17. if(!bOk) break;
18. 
19. // ..........
20. 
21.    }while(0);
22. 
23. // 释放资源
24. delete p;   
25.     p = NULL;
26. return bOk;
27. 
28. }

使用代码块,代码块内定义变量,不用考虑变量重复问题

当你的功能很复杂,变量很多你又不愿意增加一个函数的时候,使用do{}while(0);,将你的代码写在里面,里面可以定义变量而不用考虑变量名会同函数之前或者之后的重复。

相关文章
|
存储
电感器的作用及其应用
一、电感器的基本原理 电感器是一种用于存储和释放电能的 passive 设备,它的基本原理是利用线圈中的电流产生磁场,从而储存电能。电感器由一个或多个线圈组成,线圈中的导线环绕在一个或多个磁性材料的芯上。当电流通过线圈时,磁场会在芯中产生,这个磁场会储存电能。 二、电感器的类型 根据电感器的结构和特性,可以将电感器分为多种类型。常见的电感器包括固定电感器、可变电感器和互感器。 1. 固定电感器:固定电感器是指电感值不可调节的电感器。它通常由线圈和磁性芯组成,线圈中的导线匝数和磁性芯的材料和形状决定了电感器的电感值。 2. 可变电感器:可变电感器是指电感值可调节的电感器。它通常由线圈和可移动的磁
151 0
|
9天前
|
算法 编译器 C语言
宏函数以及作用
宏函数是在预处理阶段由编译器进行替换的代码片段,常用于常量定义、简单计算和代码简化。它们以 `#define` 开头,不进行类型检查,使用时需谨慎。
|
5月前
ztest中ddof起什么作用
ztest中ddof起什么作用
32 0
|
存储
电感的作用及其应用
一、什么是电感 电感是指导体中由于电流变化而产生的磁场所产生的电动势。电感是电路中的一种被动元件,通常由线圈或线圈的组合构成。当电流通过电感时,由于电流的变化,会在电感周围产生磁场,这个磁场又会产生电动势,阻碍电流的变化。因此,电感具有阻抗的特性,对交流电有较大的阻碍作用,而对直流电几乎没有影响。电感在电路中常用于滤波、储能、变压器等应用。 二、电感的作用 电感在电路中有多种作用,以下是其中几种: 1. 储能:电感能够将电能转化为磁能,当电流断开时,磁场会产生电动势,将磁能转化为电能,从而实现电能的储存。 2. 滤波:电感对交流电有较大的阻碍作用,可以用来滤除高频噪声或者直流分量,从而实现信号
226 0
函数的作用
函数的作用
105 0
|
Java Spring 容器
SmartInitializingSingleton的作用和原理
SmartInitializingSingleton的作用和原理
6327 0
|
JavaScript 前端开发
|
缓存 安全 网络协议