Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top