经常看到别人的代码里面有这一行:
/** 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);