在 C 宏中,是否应该更喜欢 do { ... } while(0,0) 而不是 do { ... } while(0) ?

发布于 2024-08-14 12:00:11 字数 408 浏览 2 评论 0原文

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

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

A customer recently performed static analysis of my employer's C codebase and gave us the results. Among useful patches was the request to change the famous do { ... } while(0) macro to do { ... } while(0,0). I understand what their patch is doing (using the sequence operator to return evaluate to the value of the second "0", so the effect is the same) but it's not clear why they'd favor the second form over the first form.

Is there a legitimate reason why one should prefer the second form of the macro, or is our customer's static analysis being overly pedantic?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦中的蝴蝶 2024-08-21 12:00:11

只是猜测为什么他们可能建议使用

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

over

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

能够告诉工具供应商解决问题可能会很好,但可能存在合法的情况,他们实际上确实想要诊断由一个常量布尔表达式。更不用说即使您说服工具供应商做出这样的更改,这对您在明年左右的时间也没有帮助,因此可能需要实际修复。

Just a guess as to why they might suggest using

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

over

do { ... } while(0)

Even though there's no behavior difference and should be no runtime cost difference between the two.

My guess is that the static analysis tool complains about the while loop being controlled by a constant in the simpler case and doesn't when 0,0 is used. The customer's suggestion is probably just so they don't get a bunch of false positives from the tool.

For example I occasionally come across situations where I want to have a conditional statement controlled by a constant, but the compiler will complain with a warning about a conditional expression evaluating to a constant. Then I have to jump through some hoops to get the compiler to stop complaining (since I don't like to have spurious warnings).

Your customer's suggestion is one of the hoops I've used to quiet that warning, though in my case it wasn't controlling a while loop, it was to deal with an "always fails" assertion. Occasionally, I'll have an area of code that should never execute (maybe the default case of a switch). In that situation I might have an assertion that always fails with some message:

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

But, at least one compiler I use issues a warning about the expression always evaluating to false. However, if I change it to:

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

The warning goes away, and everybody's happy. I'm guessing that even your customer's static analysis tool would be, too. Note that I generally hide that bit of hoop jumping behind a macro like:

#define ASSERT_FAIL( x) assert( ((x), 0))

It might be nice to be able to tell the tool vendor to fix the problem, but there might be legitimate cases where they actually do want to diagnose a loop being controlled by a constant boolean expression. Not to mention the fact that even if you convince a tool vendor to make such a change, that doesn't help you for the next year or so that it might take to actually get a fix.

黑凤梨 2024-08-21 12:00:11

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

当启用此警告时(例如使用 /W4 或 /Wall),可以根据具体情况使用这个不错的小技巧将其关闭(请参阅另一个线程)。

编辑:自 Visual Studio 2017 15.3 起,while(0) 不再发出警告(参见 常量条件)。您可以摆脱您的 (0,0)

Using while(0,0) prevents Microsoft compiler from generating a warning about a condition which is a constant (Warning C4127).

When this warning is enabled (e.g. with /W4 or /Wall), it can be shut down on a case by case basis with this nice little trick (see this other thread).

EDIT: Since Visual Studio 2017 15.3, while(0) does not emit warnings anymore (cf. Constant Conditionals). You can get rid of your (0,0) !

感情废物 2024-08-21 12:00:11

好吧,我去寻求答案:

是否有合理的理由为什么人们应该更喜欢宏的第二种形式......?

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

如果你喜欢你的代码让你的代码用猫头鹰的眼睛看着你,请使用 while (0,0)。否则,请使用 C 编程世界的其他部分所使用的内容,并告诉客户的静态分析工具来推送它。

Well, I'll go for an answer:

Is there a legitimate reason why one should prefer the second form of the macro... ?

No. There is no legitimate reason. Both always evaluate to false, and any decent compiler will probably turn the second one into the first in the assembly anyway. If there was any reason for it to be invalid in some cases, C's been around far long enough for that reason to be discovered by greater gurus than I.

If you like your code making owl-y eyes at you, use while(0,0). Otherwise, use what the rest of the C programming world uses and tell your customer's static analysis tool to shove it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文