首页IT科技do-while语句(你想知道的do{…}while(0)的作用,都在这里了)

do-while语句(你想知道的do{…}while(0)的作用,都在这里了)

时间2025-06-15 11:23:47分类IT科技浏览4115
导读:0、引言...

0            、引言

我们在嵌入式开发的过程中            ,经常可以碰到在一些宏定义或者是代码段中使用了do {...} while(0)的语句                   ,从语义上理解        ,do {...} while(0)内的逻辑就只执行一次         ,并没有循环执行                  ,粗略看来           ,似乎画蛇添足了      ,那么为什么还需要在只执行一次的逻辑外面加上一层do {...} while(0)语句呢?实际上                  ,在这些逻辑中使用do {...} while(0)的作用远大于美化你的代码              ,下面就来看看实际的使用场景            。

1                   、用于定义一个作用域   ,避免替换的时候出错

我们都知道                  ,在程序中如果一些常量参数或者代码语句反复出现                 ,就可以使用宏定义来替代                   。预处理阶段,对程序中所有出现的“宏名            ”               ,预处理器都会用宏定义中的字符串替代                    ,这称为“宏替换                   ”或“宏展开        ”        。

这样做可提高程序的通用性和易读性    ,减少不一致性            ,一个较好的宏名可以更好的让读者理解常量参数的含义;同时程序易于修改                   ,我们仅需要改变一个宏定义        ,就可以改变整个程序中出现的所有该常量或者语句         。

但是有时可能程序代码段中         ,出现多条语句重复连续的使用                  ,这样我们就可以尝试使用一个复杂的宏来替换                  。你有可能会这样定义:

  本意是在程序中当出现funA()和funB()多条语句连续使用时           ,使用REPLACE_FUN()来替换           。

1 if(判断条件) 2 REPLACE_FUN();

但是实际上在预处理的时候      ,宏展开替换后变成了:

1 if(判断条件) 2 funA(); 3 funB(); //此处funB()一定会执行                  ,造成逻辑错误

可以看出              ,funB()不会按照判断条件才去执行      。而是变成了一条独立的语句   ,而如果在宏中使用括号:

1 #define REPLACE_FUN() {funA(); funB();}

我们一般的代码习惯都会在语句的末尾加上分号                  ,因此也会出错:

1 if(判断条件) 2 REPLACE_FUN(); 3 //宏展开后为: 4 if(判断条件) 5 { 6 funA(); 7 funB(); 8 }; //此处替换后多一个分号;导致编译报错

因此                 ,针对这种多条重复语句的连续使用,如果想用宏替换实现这个作用域的功能               ,就可以考虑使用do {...} while(0)语句:

1 define REPLACE_FUN() \ 2 do{ \ 3 funA();\ 4 funB();\ 5 }while(0)\ 6 //宏展开前为: 7 if(判断条件) 8 REPLACE_FUN(); 9 //宏展开后为: 10 if(判断条件) 11 do{ 12 funA(); 13 funB(); 14 }while(0); //根据判断条件                    ,正确执行了一次逻辑

2        、避免goto语句的使用

goto语句也称为无条件转移语句    ,使用后可以从多重循环或者多个判断中直接跳出                  。对于如下例子:

1 void fun(int a) 2 { 3 if(1 == a) 4 { 5 ...//todo 6 goto exit; 7 } 8 if(2 == a) 9 { 10 ...//todo 11 goto exit; 12 } 13 exit: 14 ...//todo 15 printf("a is error"\n); 16 }

但是为了程序结构的清晰            ,还是要尽量限制goto语句的使用                   ,我们可以使用do {...} while(0)结构配合break跳出单层的循环的方法来替代这种goto的用法              。

1 int fun(int a) 2 { 3 do{ 4 if(1 == a) 5 { 6 ...//todo 7 break; 8 } 9 if(2 == a) 10 { 11 ...//todo 12 break; 13 } 14 }while(0); 15 ...//todo 16 printf("a is error"\n); 17 }

3         、定义一个单独的函数块来实现复杂的操作

当某个函数程序功能较为复杂        ,在该函数的代码段中如果不再单独定义一个函数实现部分逻辑         ,可以使用do {...} while(0)作为一个代码块                  ,将想要实现的逻辑放在do {...} while(0)中           ,同时在该在do {...} while(0)代码块中定义的变量      ,可以不用考虑和函数之前或者之后的变量名重复冲突的问题   。但是为了代码的易读性                  ,还是尽量声明不同的变量名                  。

1 int a; 2 char b; 3 int func() 4 { 5 int a = 3; 6 char b = 5; 7 do{ 8 int a; 9 char b; 10 ......//todo 11 }while(0); 12 }

4                  、避免空宏的警告

有的时候              ,程序为了不同的平台移植或者不同架构的限制   ,很多时候会先定义空宏                  ,后续再根据实际的需要看是否定义具体内容                 。但是在编译的时候                 ,这些空宏可能会给出warning,为了避免这样的warning               ,我们可以使用do{...}while(0)来定义空宏                    ,这种情况不太常见    ,因为有很多编译器已经支持空宏。

1 //空宏 2 #define EMPTY_FUN 3 //增加do{...}while(0)来定义空宏 4 #define EMPTY_FUN do{}while(0) //避免了可能的编译warning

更多技术内容和书籍资料获取            ,入群技术交流敬请关注“明解嵌入式         ”

声明:本站所有文章                   ,如无特殊说明或标注        ,均为本站原创发布               。任何个人或组织         ,在未征得本站同意时                  ,禁止复制           、盗用      、采集                  、发布本站内容到任何网站              、书籍等各类媒体平台                    。如若本站内容侵犯了原著者的合法权益           ,可联系我们进行处理    。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
python app框架flash(Python中实现WSGI的框架) 榜单大全(榜单出炉)