在linux内核中经常包括以下种类的宏:
drivers/block/ataflop.c
#define FDC_WRITE(reg,val) \
do { \
dma_wd.dma_mode_status = 0x80 | [reg]; \
udelay(25); \
dma_wd.fdc_acces_seccount = (val); \
MFPDELAY(); \
} while(0)
do语句在形式上保证宏被“调用”时代码只执行一次,与没有包含在do循环中的形式相比,并未改变语义。如果这个宏用于if语句或类似的语言要素,其优点就变得比较清楚了,如下所示:
if(condition)
FDC_WRITE(a,b) ;
初看起来,代码看上去是正确的,因为单行的if语句可以不使用{}。但如果不用do来封装,在宏扩展之后,就会出现问题:
if(condition)
dma_wd.dma_mode_status = 0x80 | [reg];
udelay(25);
dma_wd.fdc_acces_seccount = (val);
MFPDELAY();
只有第一行代码归入了if语句体。剩余的行无论if条件是否成立都会被执行,这当然不是我们想要的结果。