一位客户最近对我雇主的C代码库进行了静态分析,并向我们提供了结果.有用的补丁包括将着名do { ... } while(0)
宏更改为的请求do { ... } while(0,0)
.我理解他们的补丁正在做什么(使用序列运算符将evaluate 返回到第二个"0"的值,因此效果是相同的)但是不清楚他们为什么喜欢第二种形式而不是第一种形式.
有没有合理的理由为什么人们应该更喜欢第二种形式的宏观,还是我们客户的静态分析过于迂腐?
只是猜测他们为什么建议使用
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))
能够告诉工具供应商解决问题可能会很好,但可能存在合法的情况,他们确实想要诊断由常量布尔表达式控制的循环.更不用说即使你说服一个工具供应商进行这样的改变,这对你在明年左右的实际得到修复可能会有所帮助.
使用while(0,0)
可防止Microsoft编译器生成有关常量条件的警告(警告C4127).
当启用此警告时(例如使用/ W4或/ Wall),可以根据具体情况逐个关闭它(请参阅此其他线程).
编辑:从Visual Studio 2017 15.3开始,while(0)
不再发出警告(参见Constant Conditionals).你可以摆脱你的(0,0)
!
好吧,我会回答一下:
有没有合理的理由为什么人们应该更喜欢宏观的第二种形式......?
不,没有合理的理由.两者总是评估为false,任何体面的编译器都可能会将第二个编译成程序集中的第一个.如果在某些情况下有任何理由使其无效,那么C已经存在很长时间了,因为这个理由可以被比我更大的大师发现.
如果你喜欢你的代码让猫头鹰盯着你,请使用while(0,0)
.否则,请使用C编程世界的其他部分,并告诉客户的静态分析工具.