宏与分号

细节决定成败!

如果留心的话,可以看到 linux内核代码经常有这么奇怪的宏定义:

引用
#define wait_event(wq, condition)                                 
do {                        
        if ( condition
                break;
        __wait_event( wq , condition);
} while ( 0)

上面的宏中,while(0) 后是没有分号的,而且这个宏的 do 里执行一次,那为什么要这么定义呢?

这是因为,在程序里使用宏时,我们按照会在语句的后面加个分号 ; ,如:
wait_event(wq,conditon) ;
展开后,成为:
引用
do {                        
        if ( condition
                break;
        __wait_event( wq , condition);
} while ( 0) ;

由此可见,分号自己加上了。假如在宏定义中已在 while(0) 后添加了分号。那么对于在程序中,单独的调用这个宏,不管在宏的后面是否添加分号,那都是可以的;如果是添加了分号,那就是执行了一个空语句。

但是对于 if  ... else ... 结构,情况就不一样了,像下面的程序:
引用
#include <stdio.h>

int condition = 0;

#define wait_condition         /
do {                /
    if (condition == 10)    /
        break;        /
    condition++;        /
    sleep(1);        /
} while (0);            /

int main()
{
    int k = 1;

    if ( k == 1)
        wait_condition ;       /*添加了分号编译会报错*/
    else
        printf ( "hello world /n ");

    printf ( "%d /n " , condition);

    return ( 0);
}

编译报错
引用
[beyes@localhost programming]$ gcc -g temp.c -o temp.exe
temp.c: 在函数‘main’中:
temp.c:19: 错误:‘else’没有对应的‘if’

如果在程序中将 wait_condition;后的分号去掉,那就可以编译通过了,但这看上去就不符合 C 语言的表达式习惯。所以,在宏定义里的 while(0) 后不需要添加分号。
然而,不管宏里加不加分号,但在程序里如下使用,也不会出现问题:
引用
{ wait_condition ; }

将宏语句用大括号括起来,这样整个宏将被当成一个整体看待,所以也是正确的。

那为什么会定义 do ... while(0)  这样的形式呢?
原因是,这样做会让程序的看起来更加简洁清晰(在程序中使用大括号把一个单独的宏括起来多少总觉得有些碍眼)。
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值