此问题在此处已有答案:
do { ... } while (0) — what is it good for? [duplicate](5个答案)
Why use apparently meaningless do-while and if-else statements in macros?(9个回答)
6天前关闭
我遇到了一种在C/C++编译中定义多行宏函数的方法,它不符合任何清晰的代码约定(可能会造成性能缺陷?)。这是实现宏函数目标的唯一方法吗?开发人员会引入其他方法吗?
我知道这不是关于while(0)的第一个问题,但我正在寻找任何可能的替代方案,也许我应该只写普通函数。
我可以看到这种技术在Linux内核中使用,因此我可以说这样写是法律的吗?Linux repository search
2条答案
按热度按时间ecbunoof1#
宏和清晰的代码一开始就不能很好地结合在一起,基本上就是这样。
是的,
do ... while(0)
是一个有点笨拙的解决方案。然而,它已经成为如何做你想做的事情的事实标准。如果你找到其他聪明的替代方案,你可能会使代码不那么清晰,因为C程序员认为do ... while(0)
是既定的约定。不用担心性能,任何编译器都可以看到
do ... while(0)
只执行一次,并优化循环。根据this answer,这是唯一的方法来做你想做的事情。我不知道这在技术上是否正确,但我很确定没有好的方法可以绕过它。至少不是所有的情况。在某些情况下,它可以使用逗号运算符,如
#define FOO(x) a(x), b(x)
,但这不适用于更复杂的情况。然而,还有一些情况下,你将不得不使用这种方法。例如,如果你使用if(FOO(x))
,do-while将给予错误,但逗号和do-while都不适用于a = FOO(x)
。你可以让它与#define FOO(x) (a(x), b(x))
一起工作,但你仍然会被限制在非常简单的结构上。我尽可能远离宏,因为它们会使调试更加困难。
6qftjkof2#
一开始:宏通常更难阅读,并且通常使调试更复杂-如果适用,函数或其他替代方案,如果具体用例允许,应该是首选。
如果由于某种原因无法避免使用宏,那么实际上它可以简单地将多个表达式 Package 在一对大括号内。但是,
do { } while(0)
方法强制在之后放置一个括号,这对于产生干净的代码是理想的(宏的使用看起来像函数调用或其他类型的单个表达式),并防止使用函数之外的(尽管宏 Package 的代码通常也会这样做)。所以仅仅 Package 到大括号中显然不如do { } while(0)
方法。事实上,似乎还有另一种选择:
字符串
Chris Kline在对this answer的评论中强调了在宏参数本身包含(复杂)代码的情况下,在安全性方面优于
do { } while(0)
方法的类似问题。然而,以这种方式编写宏可能被认为是脏代码,不应该 * 应用;相反,此变体会默默地丢弃后续表达式,例如,如果通过序列(逗号)运算符追加,如:型
所以不能保证安全使用!