7

Well, this is not actually a question..

I have just occasionally found out that there's an interesting way to declare local variables inside a switch/case block. Instead of using braces inside every case block, you can write:

switch (action) {
  int res;
  int value;
case ACTION_OPEN:
  res = open(...);
  ...
  break;
case  ...
}

So, I just wonder what C/C++ compilers besides gcc support this construction? It looks like a common fall-through. Any comments on this construction are welcome!

James McNellis
  • 348,265
  • 75
  • 913
  • 977
zserge
  • 2,212
  • 2
  • 31
  • 40
  • +1, just to find out if this is legal C++ or an accident of the compiler. Could be useful if it's allowed. – Leo Davidson Nov 25 '10 at 14:37
  • An easier way is to stop using C compilers that are outdated by 11+ years. – R.. GitHub STOP HELPING ICE Nov 25 '10 at 14:49
  • Still, except for the occasional fallthrough, I still prefer the braces inside every case block for more local scoping. It is a matter of taste. – stefaanv Nov 25 '10 at 14:53
  • I changed the tag to C, as the question specifies C and the construction is completely and totally irrelevant in C++. – Puppy Nov 25 '10 at 15:10
  • 2
    @DeadMG why would it be "completely and totally irrelevant" in C++ more than in C? The tag was set by the original poster, so I doubt removing it is a good thing. C++ has additional rules covering this (`res` and `value` cannot be initialized and cannot be non-PODs). – Johannes Schaub - litb Nov 25 '10 at 15:18
  • @Johannes: You'd just declare them inside the case statement. The only advantage to this is old C compilers where you can't mix declarations and code. You're right about the non-initializing thing, though, that amazed me to see. How insane. – Puppy Nov 25 '10 at 15:44
  • @DeadMG you can declare them inside the case statement in C too. In C89 you just need to wrap a block around them (which you need anyway if you want to avoid compiler warnings (or even errors in the C++ case) like "jumps over variable declaration ..."). In any case, the question is about c++ and c ("So, I just wonder what C/C++ compilers"...) and removing the C++ tag is just wrong. – Johannes Schaub - litb Nov 25 '10 at 16:09

4 Answers4

3

The switch body is just a normal statement (in your case a compound statement, looking like { ... }) which can contain any crap. Including case labels.

This switch philosophy is abused by Duffs device.

Many people don't realize that even something like switch(0) ; is a valid statement (instead of having a compound statement, it has a null statement as body), although quite useless.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • This has nothing to do with variable declarations. Duff did not declare variables inside his `switch` statement, as the C compilers of his day would have required extra blocks (which would probably have been translated to push/pop instructions). – Fred Foo Nov 25 '10 at 14:43
  • 3
    @larsmans Duff's device has nothing to do with variable declarations, but it has all to do with abusing the switch structure employed by C and C++. In particular, that case labels are nothing really "special" but just jump labels. Once this is known, it's not surprising at all that you can put declaration statements before case labels in a switch body. – Johannes Schaub - litb Nov 25 '10 at 14:46
1

Any standards-conforming C or C++ compiler will allow this . Even an old-fashioned (pre-ISO C99) C compiler will allow this, but only because the variable declarations are at the start of a block/compound statement (denoted by {}).

Note that what follows a switch is almost a normal statement, except for the possibility of case labels:

int main(int argc, char* argv[])
{
    switch (argc)
      default:
        puts("Hello, world!");

    return 0;
}

So in ANSI C89, it's the braces that do the magic here.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
0

Strictly spoken, the case that you present with int is allowed in all three languages, but for different reasons.

C allows jumping across the definition of any local variable (arithmetic, struct, union, array...) in all cases (for C89) and in all cases but one (for C99). The exception for C99 are variable length arrays.

C++ allows this only for data types that don't have a constructor or destructor, often referred to as POD.

So if you have a type T instead of int in your example in C89 this is always valid, and in C99 and C++ it depends on the type T whether or not this is correct.

In any case, all of this easily leads to uninitialized variables, so better don't do it if you can avoid it.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
-1

I think that C99 allows to declare variable (almost) wherever you want inside blocks, so that behavior should be considered legal.. and I don't see any actual risk since it's just a declaration.

Jack
  • 131,802
  • 30
  • 241
  • 343