宏定义里为什么要加个do..while(0)?

xxldc
宏定义里为什么要加个do..while(0)?

#define INIT_LIST_HEAD(ptr) do { /
        (ptr)->next = (ptr); (ptr)->prev = (ptr); /
} while (0)

-----------------------------
这里do{}while(0)看上去没啥用?

specter117
可以利用这个宏放到if语句中,毛德操的内核书有详细解释

xi2008wang
do......while
至少会执行一次

net_robber
可以使宏看起来更像函数


以前有讨论

xxldc
[quote]原帖由 [i]net_robber[/i] 于 2008-2-17 15:13 发表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=7969876&ptid=1053426][img]http://bbs.chinaunix.net/images/common/back.gif[/img][/url]
可以使宏看起来更像函数


以前有讨论 [/quote]

以前讨论的链接在那里?

langue
也许仅仅是个习惯 :mrgreen:
就好比用 #if 0 ... #endif 来代替注释块

醉卧水云间
避免展开时被拆散.

比如
[code]
for(;;) INIT_LIST_HEAD(ptr);
[/code]

RobinsonNie
楼上正解.

cheng_lai_shun
7楼说的对!

haoji
[quote]原帖由 [i]醉卧水云间[/i] 于 2008-2-17 18:52 发表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=7970237&ptid=1053426][img]http://bbs.chinaunix.net/images/common/back.gif[/img][/url]
避免展开时被拆散.

比如

for(;;) INIT_LIST_HEAD(ptr);
[/quote]

那为什么要用do while呢, 在宏定义中加上{ }号括起来不就行了吗?


#define INIT_LIST_HEAD(ptr)  { /
        (ptr)->next = (ptr); (ptr)->prev = (ptr); /
}

RobinsonNie
转自google大街上满街都是的牛皮小广告.

1,空的宏定义避免warning:


#define foo() do{}while(0)





2,存在一个独立的block,可以用来进行变量定义,进行比较复杂的实现。





3,如果出现在判断语句过后的宏,这样可以保证作为一个整体来是实现:


#define foo(x) /


action1(); /


action2();


在以下情况下:


if(NULL == pPointer)


   foo();


就会出现action1和action2不会同时被执行的情况,而这显然不是程序设计的目的。





4,以上的第3种情况用单独的{}也可以实现,但是为什么一定要一个do{}while(0)呢,看以下代码:


#define switch(x,y) {int tmp; tmp=x;x=y;y=tmp;}


if(x>y)


switch(x,y);


else       //error, parse error before else


otheraction();





在把宏引入代码中,会多出一个分号,从而会报错。

//------------------------------------------------
使用do{….}while(0) 把它包裹起来,成为一个独立的语法单元,
从而不会与上下文发生混淆。同时因为绝大多数的编译器都能够识别do{…}while(0)这种无
用的循环并进行优化,所以使用这种方法也不会导致程序的性能降低。
也许你会说,我们代码的习惯是在每个判断后面加上{}, 就不会有这种问题了,也就不需要do...while了,如:
if(...)
{
}
else
{
}
诚然,这是一个好的,应该提倡的编程习惯,但一般这样的宏都是作为library的一部分出现的,而对于一个library的作者,他所要做的就是让其库具有通用性,强壮性,因此他不能有任何对库的使用者的假设,如其编码规范,技术水平等。