从一些经典代码中常常看到宏中使用do...while(0)的用法,感觉上do...while(0)只是在有可能要中途跳出后续一段代码的时候替换goto的一种用法,其他的就不求甚解了。
今天总算看到了wiki上对do...while(0)的解释,算是解了心中的一个疑惑。
一种情况是,这种用法可以避免在if/for下使用宏时,由于宏中的多个语句遗漏大括号而造成流程错误。就像下面这一段代码,可算是个明显的错误了。
要是使用do...while(0)将DO_SOMETHING()宏改成这样,就可以避免上述的错误了。
这可就有一个疑问了,何必加上do...while(0)呢,直接使用大括号不就好了么?
不错,只要在宏中使用大括号就可以把多条语句合成一条语句了。不过,大括号并不是个天山雪莲般可治百病的灵药哟。
看看直接使用大括号的程序吧。
看出问题了么?由于if语句下的宏后多的那个小小的分号,if下的一个语句就变成了两个语句,随后的else可就会提示你语法错误喽
而使用之前do...while(0)的宏就不会有这个问题,这也就是do...while(0)的第二个用处了。
当然,以上说的这些都是一种无奈的保护机制。如果保持一个良好的编程习惯,比如在if和else后面紧跟大括号,就不需要在乎宏上的do...while(0)了。
只是,可惜的是,当我把do...while(0)使用到公司的代码中时,却发现这触犯了Lint工具的检测规范,而直接给了我违规的结论。无奈之下,只得把do...while(0)全部删除。
或许,Lint工具并不是告诉我这样做违反编程规范,只是想提醒我要养成良好的遵守编程习惯吧
今天总算看到了wiki上对do...while(0)的解释,算是解了心中的一个疑惑。
一种情况是,这种用法可以避免在if/for下使用宏时,由于宏中的多个语句遗漏大括号而造成流程错误。就像下面这一段代码,可算是个明显的错误了。
#define DO_SOMETHING() DO_A();\
DO_B(); \
DO_C()
//
if (CONDITION_A)
DO_SOMETHING();
要是使用do...while(0)将DO_SOMETHING()宏改成这样,就可以避免上述的错误了。
#define DO_SOMETHING() do{ \
DO_A(); \
DO_B(); \
DO_C(); \
}while(0)
DO_A(); \
DO_B(); \
DO_C(); \
}while(0)
这可就有一个疑问了,何必加上do...while(0)呢,直接使用大括号不就好了么?
不错,只要在宏中使用大括号就可以把多条语句合成一条语句了。不过,大括号并不是个天山雪莲般可治百病的灵药哟。
看看直接使用大括号的程序吧。
#define DO_SOMETHING() {\
DO_A(); \
DO_B(); \
DO_C(); \
}
//
if (CONDITION_A())
DO_SOMETHING();
else
DO_SOMETHING_ELSE();
DO_A(); \
DO_B(); \
DO_C(); \
}
//
if (CONDITION_A())
DO_SOMETHING();
else
DO_SOMETHING_ELSE();
看出问题了么?由于if语句下的宏后多的那个小小的分号,if下的一个语句就变成了两个语句,随后的else可就会提示你语法错误喽
而使用之前do...while(0)的宏就不会有这个问题,这也就是do...while(0)的第二个用处了。
当然,以上说的这些都是一种无奈的保护机制。如果保持一个良好的编程习惯,比如在if和else后面紧跟大括号,就不需要在乎宏上的do...while(0)了。
只是,可惜的是,当我把do...while(0)使用到公司的代码中时,却发现这触犯了Lint工具的检测规范,而直接给了我违规的结论。无奈之下,只得把do...while(0)全部删除。
或许,Lint工具并不是告诉我这样做违反编程规范,只是想提醒我要养成良好的遵守编程习惯吧