代码之家  ›  专栏  ›  技术社区  ›  Commodore Jaeger

在C宏中,是否应该选择do{…}while(0,0)而不是do{…}while(0)?

  •  15
  • Commodore Jaeger  · 技术社区  · 16 年前

    一位客户最近对我雇主的C代码库进行了静态分析,并给出了结果。其中一个有用的补丁是请求更改著名的 do { ... } while(0) 宏到 do { ... } while(0,0) . 我了解他们的补丁在做什么(使用序列操作符 返回

    是否有合理的理由选择第二种形式的宏,或者我们客户的静态分析过于迂腐?

    3 回复  |  直到 9 年前
        1
  •  10
  •   Chris Lutz    16 年前

    好吧,我想得到一个答案:

    不,没有正当理由。两者的计算结果总是为false,任何一个好的编译器都可能会将程序集中的第二个编译器转换为第一个编译器。如果说在某些情况下它是无效的,那么C已经存在了足够长的时间,以至于这个原因被比我更伟大的古鲁发现。

    while(0,0) . 否则,请使用其他C编程世界使用的方法,并告诉客户的静态分析工具停止使用它。

        2
  •  13
  •   Michael Burr    16 年前

    只是猜测一下为什么他们会建议使用

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

    结束

    do { ... } while(0)
    

    我猜静态分析工具会抱怨 while 在更简单的情况下,循环由常量控制,而在 0,0 使用。客户的建议可能只是为了避免他们从工具中得到大量误报。

    例如,我偶尔会遇到这样的情况:我希望有一个由常量控制的条件语句,但编译器会抱怨有一个关于条件表达式求值为常量的警告。然后我必须跳过一些障碍,让编译器停止抱怨(因为我不喜欢有虚假的警告)。

    你的客户的建议是我用来消除这个警告的一个圈套,尽管在我的例子中,它并不能控制一个错误 虽然 循环,它是为了处理一个“总是失败”的断言。偶尔,我会有一个永远不会执行的代码区域(可能是开关的默认情况)。在这种情况下,我可能会有一个断言总是失败,并带有一些消息:

    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))
    

    能够告诉工具供应商解决问题可能是件好事,但在某些合法的情况下,他们确实希望诊断由常量布尔表达式控制的循环。更不用说,即使你说服了一个工具供应商做出这样的改变,这对你下一年的工作也没有帮助,因为你可能要花上一年左右的时间才能真正得到修复。

        3
  •  13
  •   Arnaud    7 年前

    使用 while(0,0) 防止Microsoft编译器生成有关常量条件的警告(警告C4127)。

    see this other thread ).

    编辑:自Visual Studio 2017 15.3以来, while(0) Constant Conditionals ).你可以摆脱你的 (0,0) !