do{...} while(0)

生来就可爱ヽ(ⅴ<●) 提交于 2019-11-29 11:23:59

前段时间看公司项目源码时,发现一个很有意思的地方,就是在很多宏函数定义里会出现do{...} while(0)。

#define ASSERT_ARRAY_EQ(expect, actual) do {    /
    ASSERT_EQ(sizeof(expect), sizeof(actual));    /
    for( size_t i = 0; i < sizeof(expect)/sizeof(int); i++)    /
    {    /
        ASSERT_EQ(expect[i], actual[i]);    /
    }    /
} while(0)

开始的时候百思不得其解,写不写这个循环似乎都只会跑一次,那是不是多此一举呢。后来仔细想了想,这么做在实际的工程项目中的确是非常有用的。

如果不使用do{...} while(0),在非嵌套使用的情况下,使用这个宏是不会出现什么问题的。

/* ...........code............ */
ASSERT_ARRAY_EQ(expected, actual);
/* ...........code............ */

上面这段代码里中间那一行会被宏函数直接替换。

然而,考虑下面这种情况:

if(...)
    ASSERT_ARRAY_EQ(expected, actual);
else
    ...

如果没有do{...} while(0),那么这段代码就会被替换成:

if(...)
    ASSERT_EQ(sizeof(expected), sizeof(actual)); 
for( size_t i = 0; i < sizeof(expected)/sizeof(int); i++)
{
    ASSERT_EQ(expected[i], actual[i]);
}
else
    ...

是不是看出问题了。

那有人就想,为什么不将宏函数直接放在花括号内呢,答案是这样的话可能会带来另一个问题:

if(...)
{
    ASSERT_EQ(sizeof(expected), sizeof(actual)); 
    for( size_t i = 0; i < sizeof(expected)/sizeof(int); i++)
    {
        ASSERT_EQ(expected[i], actual[i]);
    }
};
else
    ...

花括号后面会多一个分号,那你可能会说,我在if语句中使用这个宏函数时不在尾部添加分号不就好了吗,是的,这当然可以。但是,有时编程习惯使然,我们会不自觉的在一行代码后面加上分号,然后bug就找上门了...

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!