提问人:filberol 提问时间:11/9/2023 最后编辑:Peter Mortensenfilberol 更新时间:11/10/2023 访问量:144
do { } while(0) 替代宏定义或任何其他可能的选项 [duplicate]
do { } while(0) alternative in macro definition or any other possible options [duplicate]
问:
我遇到了一种在 C/C++ 编译中制作多行宏函数定义的方法,它不符合任何明确的代码约定(并且可能会产生性能缺陷?这是实现制作宏函数目标的唯一途径吗?开发人员会引入任何其他方法来做到这一点吗?
我看到这不是关于while(0)的第一个问题,但我正在寻找任何可能的替代方案,也许我应该只编写普通函数。
我可以看到这种技术在 Linux 内核中使用,因此我可以说这样写是合法的吗?Linux 存储库搜索
答:
宏和清晰的代码一开始就不能很好地混合。基本上就是这样。
是的,这是一个有点笨拙的解决方法。然而,它已成为如何做你想做的事的事实标准。如果你找到其他一些聪明的替代方案,你可能会使代码变得不那么清晰,因为 C 程序员认为这是既定的约定。do ... while(0)
do ... while(0)
不要担心性能。任何编译器都可以看到它只会执行一次,并且会优化循环。do ... while(0)
根据这个答案,这是做你想做的事情的唯一方法。我不知道这在技术上是否正确,但我很确定没有好的方法可以解决这个问题。至少不是在所有情况下。在某些情况下,可以使用逗号运算符,例如,但这不适用于更复杂的情况。但是,在某些情况下,您将不得不使用这种方法。例如,如果您使用 do-while 将给出错误,但逗号和 do-while 都不起作用。你可以让它使用 ,但你仍然会被限制在非常简单的结构上。#define FOO(x) a(x), b(x)
if(FOO(x))
a = FOO(x)
#define FOO(x) (a(x), b(x))
我尽量远离宏。它们往往会使调试变得更加困难。
首先:宏通常更难阅读,并且经常使调试更加复杂——如果适用,如果具体用例允许,应该首选函数或其他替代方案。
如果无论出于何种原因都无法避免宏,那么实际上只需将多个表达式包装在一对大括号中即可。但是,该方法强制在之后放置一个分号,这对于生成干净的代码是可取的(宏的使用看起来像函数调用或其他类型的单个表达式)并防止使用函数外部(尽管宏包装的代码通常也会这样做)。因此,仅仅包裹在大括号中显然不如这种方法。do { } while(0)
do { } while(0)
实际上,似乎还有另一种选择:
#define FOO if(1) { /* multiple expressions */ } else ((void)0)
克里斯·克莱恩(Chris Kline)在对类似问题的回答的评论中强调了在宏参数本身包含(复杂)代码的情况下,在安全性方面优于该方法。但是,编写此类宏可能被视为脏代码,不应应用;相比之下,此变体会静默地丢弃后续表达式,例如,如果通过序列(逗号)运算符附加,例如:do { } while(0)
FOO, bar();
// ^ unexpectedly won't get called!
所以不能保证安全使用!
评论
MYMACRO( SomeFunc(i)==true, {break;} )
FOO, bar();
FOO + bar()
bar()
do{ }while(0)
static_assert(true)
true
false
if(0);else{ ... }
上一个:如何在 Cmake 中定义宏列表
评论
do ... while (0)
do {} while(0)