客户最近对我雇主的C代码库进行了静态分析,并向我们提供了结果。有用的补丁包括将着名的do { ... } while(0)
宏更改为do { ... } while(0,0)
的请求。我理解他们的补丁正在做什么(使用序列运算符 return 计算得到第二个“0”的值,所以效果是一样的)但是不清楚他们为什么喜欢第二个形成第一种形式。
有没有合理的理由为什么人们应该更喜欢第二种形式的宏观,还是我们的客户的静态分析过于迂腐呢?
答案 0 :(得分:13)
只是猜测他们为什么建议使用
do { ... } while(0,0)
在
do { ... } while(0)
即使没有行为差异,两者之间也不应存在运行时成本差异。
我的猜测是静态分析工具抱怨while
循环在更简单的情况下由常量控制,而在使用0,0
时则不会。客户的建议可能只是因为他们没有从工具中得到一堆误报。
例如,我偶尔会遇到一些情况,我想要一个由常量控制的条件语句,但编译器会抱怨有关条件表达式求值为常量的警告。然后我必须跳过一些箍来让编译器停止抱怨(因为我不喜欢有虚假的警告)。
你的客户的建议是我用来平息警告的箍之一,尽管在我的情况下它不是控制while
循环,而是处理“总是失败”的断言。偶尔,我会有一个永远不会执行的代码区域(可能是交换机的默认情况)。在那种情况下,我可能会有一个总是失败的断言:
assert( !"We should have never gotten here, dammit...");
但是,我使用的至少一个编译器会发出关于表达式总是评估为false的警告。但是,如果我将其更改为:
assert( ("We should have never gotten here, dammit...", 0));
警告消失了,每个人都很开心。我猜你的客户的静态分析工具也是如此。请注意,我通常会隐藏在一个宏后面跳的那个箍:
#define ASSERT_FAIL( x) assert( ((x), 0))
能够告诉工具供应商解决问题可能会很好,但可能存在合法的情况,他们确实想要诊断由常量布尔表达式控制的循环。更不用说即使你说服一个工具供应商做出这样的改变,这对你在未来一年左右的时间内没有帮助,可能需要实际修复。
答案 1 :(得分:12)
使用while(0,0)
可防止Microsoft编译器生成有关常量条件的警告(警告C4127)。
当启用此警告时(例如使用/ W4或/ Wall),可以通过这个漂亮的小技巧(see this other thread)逐个关闭它。
编辑:自Visual Studio 2017 15.3起,while(0)
不再发出警告(参见Constant Conditionals)。你可以摆脱你的(0,0)
!
答案 2 :(得分:11)
好吧,我会回答:
有没有合理的理由为什么人们应该更喜欢第二种形式的宏??
没有。没有正当理由。两者总是评估为false,任何体面的编译器都可能会将第二个编译成程序集中的第一个。如果在某些情况下有任何理由使它无效,那么C已经存在很长时间了,因为这个理由可以被更多的大师发现而不是我。
如果您喜欢用猫头鹰眼睛看你的代码,请使用while(0,0)
。否则,使用C编程世界的其他部分使用并告诉客户的静态分析工具来推送它。