8

In a coding style question about infinite loops, some people mentioned they prefer the for(;;) style because the while(true) style gives warning messages on MSVC about a conditional expression being constant.

This surprised me greatly, since the use of constant values in conditional expressions is a useful way of avoiding #ifdef hell. For instance, you can have in your header:

#ifdef CONFIG_FOO
extern int foo_enabled;
#else
#define foo_enabled 0
#endif

And the code can simply use a conditional and trust the compiler to elide the dead code when CONFIG_FOO isn't defined:

if (foo_enabled) {
    ...
}

Instead of having to test for CONFIG_FOO every time foo_enabled is used:

#ifdef CONFIG_FOO
if (foo_enabled) {
    ...
}
#endif

This design pattern is used all the time in the Linux kernel (for instance, include/linux/cpumask.h defines several macros to 1 or 0 when SMP is disabled and to a function call when SMP is enabled).

What is the reason for that MSVC warning? Additionally, is there a better way to avoid #ifdef hell without having to disable that warning? Or is it an overly broad warning which should not be enabled in general?

Community
  • 1
  • 1
CesarB
  • 43,947
  • 7
  • 63
  • 86

4 Answers4

10

A warning doesn't automatically mean that code is bad, just suspicious-looking.

Personally I start from a position of enabling all the warnings I can, then turn off any that prove more annoying than useful. That one that fires anytime you cast anything to a bool is usually the first to go.

Menkboy
  • 1,595
  • 10
  • 12
5

I think the reason for the warning is that you might inadvertently have a more complex expression that evaluates to a constant without realizing it. Suppose you have a declaration like this in a header:

const int x = 0;

then later on, far from the declaration of x, you have a condition like:

if (x != 0) ...

You might not notice that it's a constant expression.

Ferruccio
  • 98,941
  • 38
  • 226
  • 299
2

I believe it's to catch things like

 if( x=0 )

when you meant

 if( x==0 )
James Curran
  • 101,701
  • 37
  • 181
  • 258
  • Good point. This is one reason one sees "backwards" comparisons like "if (0 == x)" -- if you miss one = sign, the compiler catches it! – bog Oct 22 '08 at 03:51
  • If that's what it wants to catch, couldn't it catch only that (assignment within a conditional) instead of a more general warning? – CesarB Oct 22 '08 at 03:54
  • 1
    That generates a different warning. With VC++ it's: Compiler Warning (level 4) C4706 assignment within conditional expression – Ferruccio Oct 22 '08 at 04:00
0

A simple way to avoid the warning would be:

#ifdef CONFIG_FOO
extern int foo_enabled;
#else
extern int foo_enabled = 0;
#endif
bog
  • 1,513
  • 7
  • 12
  • Are you sure you can extern a variable and at the same time give it a value? What if it's initialized to a different value where it's defined? "static const int foo_enabled = 0;" would be a better choice. – Jim Buck Oct 22 '08 at 04:59