经常看到别人的代码里面有这一行:
/**
rief Data Synchronization Barrier
details Acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
#define __DSB() do {
__schedule_barrier();
__dsb(0xF);
__schedule_barrier();
} while (0U)
这种宏的用途有什么好处?
Linux 的创始人是这么说的:
do{...}while(0)在C中是唯一的构造程序,让你定义的宏总是以相同的方式工作,这样不管怎么使用宏(尤其在没有用大括号包围调用宏的语句),宏后面的分号也是相同的效果.
那么不这样定义呢?比如:
#define foo(x) bar(x); baz(x)
然后你可能这样调用:
foo(wolf);
这将被宏扩展为:
bar(wolf); baz(wolf);
但是如下调用:
if (!feral)
foo(wolf);
那么扩展后可能就不是你所期望的结果,上面语句将扩展为:
if (!feral)
bar(wolf);
baz(wolf);
改进一下,试一下如此定义:
#define foo(x) { bar(x); baz(x); }
那么上一个有问题的可就解决了吗?不是的,他展开是如此:
if (!feral) {
bar(wolf);
baz(wolf);
};
else
bin(wolf);
如果是推荐定义中的呢,如下:
if (!feral)
do { bar(wolf); baz(wolf); } while (0);
他等于:
if (!feral) {
bar(wolf);
baz(wolf);
}
展开是:
if (!feral)
do
{
bar(wolf);
baz(wolf);
}
while (0);
else
bin(wolf);
这可能算是一种C语言陷阱.当然do{...}while(0)远远不止这个用途.比如说优化Goto语句,因为Goto语句不太容易读,而且容易出BUG,如下是Goto用法的片段.
int foo()
{
somestruct* ptr = malloc(...);
dosomething...;
if(error)
{
goto END;
}
dosomething...;
if(error)
{
goto END;
}
dosomething...;
END:
free(ptr);
return 0;
}
他可以改成:
int foo()
{
somestruct* ptr = malloc(...);
do{
dosomething...;
if(error)
{
break;
}
dosomething...;
if(error)
{
break;
}
dosomething...;
}while(0);
free(ptr);
return 0;
}
还有一种是定义空的宏定义,避免编译器在警告:
#define EMPTYMICRO do{}while(0)
可见,不仅仅可以做函数区块,还可以做各种其他用途,还是很好用的.
直接用一对{},两者有什么区别?
@myxiaonia 在文中有说了,如果不加,会这样.
if (!feral) {
bar(wolf);
baz(wolf);
};
else
bin(wolf);