一位客户最近对我雇主的 C 代码库进行了静态分析,并向我们提供了结果。有用的补丁之一是更改著名的请求 do { ... } while(0) 宏到 do { ... } while(0,0). 。我了解他们的补丁正在做什么(使用序列运算符 返回 评估为第二个“0”的值,因此效果是相同的)但不清楚为什么他们更喜欢第二种形式而不是第一种形式。

是否有合理的理由为什么人们应该更喜欢宏的第二种形式,或者我们客户的静态分析是否过于迂腐?

有帮助吗?

解决方案

好了,我会去一个答案:

  

是否有正当的理由为什么要喜欢宏的第二个形式...?

没有。没有正当的理由。双方总是为false,任何像样的编译器可能会变成第二个进入组装第一反正。如果有任何理由为它在某些情况下无效,C一直围绕远远不够长,因此要由比我更大的大师发现的。

如果你喜欢你的代码,你让猫头鹰-Y的眼睛,用while(0,0)。否则,用什么C编程世界其他地区使用,并告诉你的客户的静态分析工具来推它。

其他提示

只是一个猜测,为什么他们会使用提示

do { ... } while(0,0)

do { ... } while(0)

虽然没有行为差异,应该是两者之间没有运行成本差异。

我的猜测是,静态分析工具抱怨有while环被一个恒定在简单的情况控制,并使用0,0时没有。客户的意见可能只是使他们不从工具得到一堆误报。

例如我偶尔遇到其中我想有由恒定控制的条件语句的情况下,但是编译器将与约一个的条件表达式的常数警告抱怨。然后,我必须通过一些跳火圈,让编译器停止抱怨(因为我不喜欢有虚假警告)。

您客户的建议是我用安静的警告箍之一,但在我的情况下,它并没有控制while循环,这是对付一个“总是失败”的断言。偶尔,我会的代码,不应该执行区域(可能是交换机的默认情况下)。在这种情况下,我可能有一个总是失败的一些消息的断言:

assert( !"We should have never gotten here, dammit...");

但是,至少一个编译器我用的问题一个关于表达式总是评估为假警报。但是,如果将它改变为:

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) 不再发出警告(参见 常量条件句)。你可以摆脱你的 (0,0) !

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top