C语言 do { } while(0)宏定义中的替代项或任何其他可能的选项[重复]

piztneat  于 2023-11-16  发布在  其他
关注(0)|答案(2)|浏览(104)

此问题在此处已有答案

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

ecbunoof

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))一起工作,但你仍然会被限制在非常简单的结构上。
我尽可能远离宏,因为它们会使调试更加困难。

6qftjkof

6qftjkof2#

一开始:宏通常更难阅读,并且通常使调试更复杂-如果适用,函数或其他替代方案,如果具体用例允许,应该是首选。
如果由于某种原因无法避免使用宏,那么实际上它可以简单地将多个表达式 Package 在一对大括号内。但是,do { } while(0)方法强制在之后放置一个括号,这对于产生干净的代码是理想的(宏的使用看起来像函数调用或其他类型的单个表达式),并防止使用函数之外的(尽管宏 Package 的代码通常也会这样做)。所以仅仅 Package 到大括号中显然不如do { } while(0)方法。
事实上,似乎还有另一种选择:

#define FOO if(1) { /* multiple expressions */ } else ((void)0)

字符串
Chris Kline在对this answer的评论中强调了在宏参数本身包含(复杂)代码的情况下,在安全性方面优于do { } while(0)方法的类似问题。然而,以这种方式编写宏可能被认为是代码,不应该 * 应用;相反,此变体会默默地丢弃后续表达式,例如,如果通过序列(逗号)运算符追加,如:

FOO, bar();
//   ^ unexpectedly won't get called!


所以不能保证安全使用!

相关问题