宏定义
- 避免空宏引起的warning
内核中由于不同架构的限制,很多时候会用到空宏,在编译的时候,空宏会给出warning,为了避免这样的warning,就可以使用do{}while(0)来定义空宏:
#define EMPTYMICRO do{}while(0)
- 存在一个独立的block,可以用来进行变量定义,进行比较复杂的实现。
#define MACRO_NAME(para) do{macro content}while(0)
- 如果出现在判断语句过后的宏,这样可以保证作为一个整体来实现。
如果没有使用do{}while(0)定义这样的宏,进而在if语句后扩展这样的宏又没用{}括起来,会导致宏展开后语法逻辑错误。故这也是为什么单条if else语句也推荐使用{}括起来的原因之一。
使用do{….}while(0) 把它包裹起来,成为一个独立的语法单元,从而不会与上下文发生混淆。并且可以在宏之后添加分号,符合语句结束添加一个分号的习惯。
绝大多数的编译器都能够识别do{…}while(0)这种无用的循环并进行优化,所以使用这种方法并不会导致程序的性能降低。
另外,GCC提供了Statement-Expressions用以替代do{…}while(0); 所以在GCC中也可以这样定义宏: 注意,MSVC不支持这种语义。
#define DOSOMETHING() ({\\
foo1(); \\
foo2(); \\
})
一般这样的宏都是作为library的一部分出现的,而对于一个library的作者,他所要做的就是让其库具有通用性,强壮性,因此他不能有任何对库的使用者的假设,如其编码规范,技术水平等。
巧用do{}while(0)替代goto
C++中goto语句是被限制使用的。 c++原生不支持在goto和label中间定义自动变量,如map vector等复杂的,或者自定义类型变量。
class Test {
public:
Test() {
cout << "Test()" << endl;
}
~Test() {
cout << "~Test()" << endl;
}
};
void func() {
int i = 10;
goto ERROR;
Test t;
ERROR:
return;
}
上面例子func方法中t执行了析构,未执行构造。在一些变量为vector等复杂的情况下,程序会触发core或者死循环,原因就是没经过构造过程容器内部地址是未初始化的,也就是常说的undefined behaviour。 在生产环境中,通过在goto之前定义变量解决了这个问题,但是本质上,c++对goto做了使用限制,因此在c++程序中不要轻易使用goto。 可以使用do{ // break; }whiile(0);替代goto的使用。
int foo()
{
somestruct* ptr = malloc(...);
do{
dosomething...;
if(error)
{
break;
}
dosomething...;
if(error)
{
break;
}
dosomething...;
}while(0);
free(ptr);
return 0;
}
这里将函数主体使用do()while(0)包含起来,使用break来代替goto,后续的处理工作在while之后,就能够达到同样的效果。
https://blogread.cn//it/article/5907 https://blog.csdn.net/fxy0325/article/details/89856623
|