do-while语句(你想知道的do{…}while(0)的作用,都在这里了)
0 、引言
我们在嵌入式开发的过程中 ,经常可以碰到在一些宏定义或者是代码段中使用了do {...} while(0)的语句 ,从语义上理解 ,do {...} while(0)内的逻辑就只执行一次 ,并没有循环执行 ,粗略看来 ,似乎画蛇添足了 ,那么为什么还需要在只执行一次的逻辑外面加上一层do {...} while(0)语句呢?实际上 ,在这些逻辑中使用do {...} while(0)的作用远大于美化你的代码 ,下面就来看看实际的使用场景 。
1 、用于定义一个作用域 ,避免替换的时候出错
我们都知道 ,在程序中如果一些常量参数或者代码语句反复出现 ,就可以使用宏定义来替代 。预处理阶段,对程序中所有出现的“宏名 ” ,预处理器都会用宏定义中的字符串替代 ,这称为“宏替换 ”或“宏展开 ” 。
这样做可提高程序的通用性和易读性,减少不一致性 ,一个较好的宏名可以更好的让读者理解常量参数的含义;同时程序易于修改 ,我们仅需要改变一个宏定义 ,就可以改变整个程序中出现的所有该常量或者语句 。
但是有时可能程序代码段中 ,出现多条语句重复连续的使用 ,这样我们就可以尝试使用一个复杂的宏来替换 。你有可能会这样定义:
本意是在程序中当出现funA()和funB()多条语句连续使用时 ,使用REPLACE_FUN()来替换 。
但是实际上在预处理的时候 ,宏展开替换后变成了:
可以看出 ,funB()不会按照判断条件才去执行 。而是变成了一条独立的语句 ,而如果在宏中使用括号:
我们一般的代码习惯都会在语句的末尾加上分号 ,因此也会出错:
因此 ,针对这种多条重复语句的连续使用,如果想用宏替换实现这个作用域的功能 ,就可以考虑使用do {...} while(0)语句:
2 、避免goto语句的使用
goto语句也称为无条件转移语句,使用后可以从多重循环或者多个判断中直接跳出 。对于如下例子:
但是为了程序结构的清晰 ,还是要尽量限制goto语句的使用 ,我们可以使用do {...} while(0)结构配合break跳出单层的循环的方法来替代这种goto的用法 。
3 、定义一个单独的函数块来实现复杂的操作
当某个函数程序功能较为复杂 ,在该函数的代码段中如果不再单独定义一个函数实现部分逻辑 ,可以使用do {...} while(0)作为一个代码块 ,将想要实现的逻辑放在do {...} while(0)中 ,同时在该在do {...} while(0)代码块中定义的变量 ,可以不用考虑和函数之前或者之后的变量名重复冲突的问题 。但是为了代码的易读性 ,还是尽量声明不同的变量名 。
4 、避免空宏的警告
有的时候 ,程序为了不同的平台移植或者不同架构的限制 ,很多时候会先定义空宏 ,后续再根据实际的需要看是否定义具体内容 。但是在编译的时候 ,这些空宏可能会给出warning,为了避免这样的warning ,我们可以使用do{...}while(0)来定义空宏 ,这种情况不太常见,因为有很多编译器已经支持空宏。
更多技术内容和书籍资料获取 ,入群技术交流敬请关注“明解嵌入式 ”
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!