do...while(0) 在宏定义中的应用

 这是一个奇怪的循环,它根本就只会运行一次,为什么不去掉外面的do{...}while结构呢?我曾一度在心里把它叫做“怪圈”。原来这也是非常巧妙的技巧。在工程中可能经常会引起麻烦,而上面的定义能够保证这些麻烦不会出现。下面是解释:

一方面


假设有这样一个宏定义

#define macro(condition) /

if(condition) dosomething()

现在在程序中这样使用这个宏:

if(temp)
    macro(i);
else
    doanotherthing();

一切看起来很正常,但是仔细想想。这个宏会展开成:

if(temp)
    if(condition) dosomething();
else
    doanotherthing();

这时的else不是与第一个if语句匹配,而是错误的与第二个if语句进行了匹配,编译通过了,但是运行的结果一定是错误的。

为了避免这个错误,我们使用do{….}while(0) 把它包裹起来,成为一个独立的语法单元,从而不会与上下文发生混淆。同时因为绝大多数的编译器都能够识别do{…}while(0)这种无用的循环并进行优化,所以使用这种方法也不会导致程序的性能降低。

另一方面

这是为了含多条语句的宏的通用性
因为默认规则是宏定义最后是不能加分号的,分号是在引用的时候加上的

比如定义了一个宏fw(a,b),那么在c文件里一定是这样引用
fw(a,b);

如果不用do...while,那么fw就得定义成:
#define fw(a,b) {read((a));write((b));}   
那这样fw(a,b);展开后就成了:
{read(a);write(b);};
最后就多了个分号,这是语法错误

而定义成do...while的话,展开后就是:
do{read(a);write(b);}while(0);  完全正确
所以要写一个包含多条语句的宏的话,不用do...while是不可能的

你可能感兴趣的:(c,优化,编译器)