17

在回答这篇文章时,我建议使用do {...} while(0)多行宏。

在 MSVC 上,我发现这段代码抛出:

warning C4127: conditional expression is constant

为了使代码无警告,我需要选择以下丑陋的替代方案之一:

选项1

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4127)
#endif
code_using_macro_that_generates_C4217;
#ifdef _MSC_VER
#pragma warning(pop)
#endif

选项 2
将我的宏定义为:

#define MULTI_LINE_MACRO do { ... } while(0,0)

或者

#define MULTI_LINE_MACRO do { ... } while((void)0,0)

一些程序员也将其称为“猫头鹰”,因为(0,0)它看起来像猫头鹰。

选项 3
定义一个不会生成警告的新宏 WHILE_0 并使用它来代替while(0)

问题
我相信所有的选择或多或少都是可怕的。为什么 MSVC 会为看似正确的代码生成此警告,并激励我在代码中添加一些丑陋以保持代码警告免费?

我相信条件中的常量表达式是完全有效和有用的,特别是在基于编译器优化代码能力的构造中。

此外,我没有得到这样warning C4127的代码:

void foo(unsigned bar)
{
    while (bar >= 0)
        ;
} 

我的问题是:这不是warning C4127: conditional expression is constant完全没用,也不会激发丑陋的代码吗?这个警告是否有助于编写更好的代码?

4

2 回答 2

5

我不认为它是有用的。相反,有更多的误报,而不仅仅是do .. while(0)成语。想想像这样的结构

if(sizeof(long) == 8) { /* ... */ }
if(SOME_CONSTANT_MACRO) { /* ... */ }

前者不能被#if指令取代,后者可以,但一些编码风格指南更喜欢这个if版本,因为仍然对死代码进行语法检查(在其他平台上或在其他编译时配置上没有死),有些人发现读起来更好。

警告(除了标准要求的那些,其中大部分应该被视为错误)通常是针对有效的代码发出的,但可能会做一些超出预期的事情。if(0)或者像这样的事情看起来很傻,但看起来除了“语法检查这个否则死代码”之外的其他东西。这可能会让读者感到困惑,但它是明确的,我不明白这怎么会意外发生。

从到目前为止给出的示例中(我还没有自己测试 MSVC),似乎警告是针对 C 语言意义上的常量表达式(也就是说,不是可以常量折叠但在语法上的东西不是一个常量表达式),所以它不是为if(array), or发出的if(function)(例如gcc -Wall警告什么,因为它可能是一个函数调用)。

while(0,0)更糟糕的是,在我看来,它会在没有副作用的情况下触发gcc -Wall逗号运算符左侧的警告,我可以想象这个警告偶尔有用(通常很容易避免)。此警告随 消失while((void)0,0)

我建议关闭警告。

于 2015-03-18T11:22:24.173 回答
3

条件表达式是常量的警告肯定有用的。在许多情况下,它可以指向代码中的逻辑错误。

例如,如果您编写如下内容:

if (x != NULL) { /* ... */ }

wherex是一个数组对象,表达式有效,但表达式x衰减为指向数组初始元素的指针,该指针不能为空指针。我不知道这是否会产生相同的错误,但这是同类事物的一个示例。

当然,它并不总是有用的。在你的情况下,

do { /* ... */ } while (0)

惯用语是编写宏定义的最佳方式,该宏定义旨在用于需要语句的上下文中。在另一个上下文中使用while (0)可能是一个逻辑错误 [*]。

不幸的是,您的编译器没有将其识别为常见习语。生成好的警告很棘手;编译器必须超越语言规则并推断程序员的意图。

在这种情况下,使用一些特定于编译器的方法来抑制警告(只要它不会破坏其他编译器的代码)可能是最好的方法。在所有情况下使用命令行选项来抑制警告将是矫枉过正的;您可能会错过代码中其他地方的有效警告。

显然是写while (0,0)而不是while (0)避免警告。如果您这样做,您应该添加一条注释,清楚地表明它是您特定编译器的解决方法。while (0,0)编译器不应该警告或任何其他等效代码没有特别的原因。

do { /* ... */ } while (0)[*]如果你想用break它跳出来,写一个语句是有意义的。

于 2015-03-16T16:18:12.067 回答