曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 4877|回复: 0
打印 上一主题 下一主题

do{} while(0)

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2010-7-25 00:35:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在 Linux 内核中,经常会看到 do{} while(0) 。也许会认为,do{}while(0) 毫无意义,因为它只会执行一次,加不加 do{}while(0) 效果完全一样。实际上,do{}while(0) 主要用于宏定义中。如下面一个简单的宏定义:
#define SAFE_FREE(p) do{ free(p); p = NULL; } while (0)
现将上面的宏改写为另外的形式:
#define SAFE_FREE(p) free(p); p = NULL;
那么编译下面的程序就会出错:
#include <stdio.h>
#include <stdlib.h>

#define SAFE_FREE(p) free(p); p = NULL;
int main()
{
    int *p = malloc (sizeof(int));
    *p = 10;

    if (p != NULL)
        SAFE_FREE(p);
    else
        ;

    return (0);
}
编译错误提示:
 gcc -g do_while.c -o do_while
do_while.c: In function ‘main’:
do_while.c:13: error: ‘else’ without a previous ‘if’
这是因为展开后,if 下面有两条语句,从而导致了 else 没有匹配的 if,所以编译失败。当然,如果将 free(p); p = NULL; 这两条语句用大括号括起来就不会有问题。但是如果在宏中将其括起,还是不会解决问题,因为在 C 语言中,每个语句后面加分号是一种约定成俗的习惯。所以,所若宏被定义为 #define SAFE_FREE(p) {free(p); p = NULL;} 在展开时会变成:
if (p != NULL) {
     free(p);
     p = NULL;
};
else
   ... ...
上面,宏展开后,在右大括号后加了一分号,这一分号实际上是一条空语句,它亦使 else 失去了匹配,从而编译报错。

如果使用了 do{}while(0),那么情况就不一样了。同样的代码会展开为:
if (p != NULL)
   do {
         free(p); p = NULL)
   } while(0);
 else
    ... ...
这样不会再出现编译问题。do{}while(0) 使用完全是为了保证宏定义的使用者能无编译错误地使用宏,它不对其使用者做任何假设。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-10 20:15 , Processed in 0.072042 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表