17

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?

Community
  • 1
  • 1
Commodore Jaeger
  • 32,280
  • 4
  • 54
  • 44
  • 5
    Your customer's static analysis tool was being overly something, that's for sure. – Chris Lutz Dec 05 '09 at 22:46
  • 7
    I'd go for "too overly redundant". – Greg Hewgill Dec 05 '09 at 22:47
  • 3
    I can't think of any reason to do this. Perhaps some tool complains with a while(0) condition along the lines of "this will never happen" but any such tool should 1) recognize that this is a very common idiom in C with macros and 2) differentiate between do...while(0) and while(0){}. Have you asked them for a rationale? – Robert Gamble Dec 05 '09 at 22:50
  • 2
    Maybe the static analysis tool thinks `while(0,0)` looks cooler. I can kind of see where it's coming from. – Chris Lutz Dec 05 '09 at 22:51
  • 20
    Yeah, `(0,0)` looks like an owl. Maybe they thought your code needs more owls. – Steve Jessop Dec 05 '09 at 22:54
  • @Steve - Coincidentally, I made the same animal connection in my answer. – Chris Lutz Dec 05 '09 at 22:55
  • 1
    I would definitely like to know what the reason for recommending this was, if you ask them and find out, please update your question with their response. – Robert Gamble Dec 05 '09 at 22:59
  • 3
    I've got it. The code is has to handle mouseover events, and the owls are there to catch the mice. – bmargulies Dec 05 '09 at 23:18
  • 6
    Well in C and C++, `0,0` is not a constant expression, but `0` is. So it's more likely that compilers warn about the latter than the former. But it's also more likely compilers optimize away the latter than the former - so i don't quite see what they win when changing it. – Johannes Schaub - litb Dec 06 '09 at 09:35

3 Answers3

14

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.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • 2
    +1 This might be it, but if this is the case these warnings should just be disabled with command line options. Why jump through hoops when you can just turn off the hoops that aren't necessary? – Chris Lutz Dec 06 '09 at 09:28
  • 1
    Well, for one, futzing around with compiler or tool options might be considered a form of hoop jumping. Screwing around with the makefiles or whatever controls your build is often much more black magic than C preprocessor hackery is (and that's saying a lot). For another, you might not want the warning to be disabled for everything - maybe just for the debugging macros that seem to need these stupid tricks. – Michael Burr Dec 06 '09 at 09:54
  • 1
    And now my static analysis complains, "Redundant left argument to comma." Sometimes you just can't win. – John Mar 06 '14 at 22:26
13

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

Arnaud
  • 3,765
  • 3
  • 39
  • 69
11

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.

Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
  • It does not evaluate to anything; and do-loop is not an expression and has no value. Try assigning it int x = macro() ;, and it fails to compile. – Clifford Dec 05 '09 at 22:58
  • 1
    I'm referring to the evaluation of `0` vs. `0,0`, not the `do { } while(0)` loop in general. – Chris Lutz Dec 05 '09 at 23:00
  • Ok; I was still trying to fathom the benefit as a whole. – Clifford Dec 05 '09 at 23:02
  • The continuation expressions are not what they seem. – Steve Jessop Dec 05 '09 at 23:48
  • Thanks. I couldn't think of a good reason and I'm glad the Internet confirmed it for me. – Commodore Jaeger Dec 06 '09 at 02:36
  • 1
    "What benefit?": The benefit conveyed by using 0,0 in the while loop condition. The static analysis seems to believe there is one, but this answer, though accepted does not reveal that so we are left wondering. – Clifford Dec 06 '09 at 08:35
  • My point (and the point of my answer) is that there _is_ no benefit. Any benefit the static analysis tool imagines to be there cannot possibly exist. – Chris Lutz Dec 06 '09 at 09:26
  • 1
    @Chris: I get *your* point, but out of curiosity, I was hoping that someone could enlighten us as to why the tool was advising this - even if the thinking were flawed. I can find no reference to such an idiom anywhere. Even teh MISRA C guidelines do not advise this. It would help if the OP were to tell us what the tool was perhaps? – Clifford Dec 07 '09 at 10:34
  • It would be nice to know, but it's a tool that the OP says was used by a customer, so we may never get to find out. – Chris Lutz Dec 07 '09 at 23:21
  • 3
    0,0 makes VC++ warning 4127 go away. That's the legitimate reason this pattern exists. If you think 0,0 is an unacceptable hack, then why do you think using do{}while(0) itself isn't a worse hack? – ThreeBit Apr 02 '14 at 22:59
  • @Clifford the tool is probably advising this because under a literalist interpretation of the C standard (C11 6.6), an expression containing a comma operator is not a constant. Presumably the tool used a very simplistic approach less advanced than what most compilers are capable of (in contrast, most reasonable tools have no difficulty recognizing when `do ... while (0)` comes from a macro expansion and ignoring it). – Alex Celeste Jul 17 '17 at 10:54
  • @Leushenko : Thanks, although I made that comment in 2009 - I have long since ceased to care! I doubt a compiler "recognizes a macro expansion", it simply recognises an "always false" expression (to the same effect). – Clifford Jul 17 '17 at 11:26
  • @Clifford nah I mean for warnings (not codegen), real-world compilers don't usually actually separate the phases, they maintain "origin" histories and can know when to silence warnings because they recognized a common idiom like a constant control flow structure that came from a macro expansion. – Alex Celeste Jul 17 '17 at 11:37