views:

379

answers:

6

I was just made aware of a bug I introduced, the thing that surprised me is that it compiled, is it legal to switch on a constant?

Visual Studio 8 and Comeau both accept it (with no warnings).

switch(42) { // simplified version, this wasn't a literal in real life
    case 1:
        std::cout << "This is of course, imposible" << std::endl;  
}
+2  A: 

Yes, its legal.

Visage
+2  A: 

Yes, it's perfectly legal to switch on any integer expression. It's the same as switching on an integer value returned by a function - a construct used quite often.

sharptooth
+16  A: 

Not everything that makes sense to the compiler makes sense!

The following will also compile but makes no sense:

if (false)
{
   std::cout << "This is of course, imposible" << std::endl;
}

It's up to us as developers to spot these.

ChrisF
@Chris: #define DEBUG false ... and later ... if (DEBUG) { fprintf(stderr, "DEBUG: You can't get here either, so a good optimizing compiler will remove this whole block." }
corlettk
I've seen such code being abused like this: for(....) { if(false) { end: ....; } .... if(stuff) goto end; }
Johannes Schaub - litb
+2  A: 

Yes, but why you'd want to (unless debugging) is another matter.

It's similar to if (0) or while (true).

graham.reeds
But while(true) with a break is a fairly usual construct.
ChrisF
while(true) isn't as crazy as it might seem and forms the basis of a few constructs, there are probably better approaches but it is used. if(0) or if (false) do fall squarely in the 'Why!?' camp :)
Lazarus
I was just demonstrating that literals/constants in switching/looping statements weren't unusual.
graham.reeds
People that know stuffs will always do for(;;) { ... } instead of while(1) { ... } to avoid compiler warnings about "constant condition"
Johannes Schaub - litb
+16  A: 

It's not impossible that switching on a constant makes sense. Consider:

void f( const int x ) {
   switch( x ) {   
   ...
   }
}

Switching on a literal constant would rarely make sense, however. But it is legal.

Edit: Thinking about it, there is case where switching on a literal makes perfect sense:

int main() {
    switch( CONFIG ) {
           ...
    }
}

where the program was compiled with:

g++ -DCONFIG=42 foo.cpp
anon
+1 fantastic example
MeThinks
+1, good example. Also template code or generated code could easily produce such a construct.
j_random_hacker
+3  A: 

One good reason for this being legal is that the compiler might well be able to resolve the value at compile time, depending on what stage of development you're at.

E.g. you might use something like this for debugging stuff:

int glyphIndex;
...
#if CHECK_INVALID_GLYPH
glyphIndex = -1;
#endif

switch (glyphIndex)
    ...

The compiler knows for certain that glyphIndex is -1 here, so it's as good as a constant. Alternatively, you might code it like this:

#if CHECK_INVALID_GLYPH
const int glyphIndex = -1;
#else
int glyphIndex = GetGlyph();
#endif

You wouldn't really want to have to change the body of your switch statement just so you could make little changes like this, and the compiler is perfectly capable of rationalising the code to eliminate the parts that will never be executed anyway.

Nik