Insert a case label into an if ... else statement

g ++ accepts this code, and it behaves as I expected:

#include <cassert> void example (int value, bool condition) { switch (value) { case 0: if (condition) { case 1: assert(condition || value == 1); } else { assert(!condition && value == 0); } assert(value == 0 || value == 1); } } int main () { example(0, false); example(1, false); example(0, true); example(1, true); } 

Maybe this is a silly basic question, but aside from the smell of code, does C ++ really put the case label inside the if...else block, and all the correct compilers correctly generate code that jumps through else when entering through case 1 ?

+6
source share
2 answers

As for C ++ (project N3936):

  • and default tags by themselves do not alter the control flow , which freely extends to such tags .
  • Usually, the substitution that is the subject of the switch is complex, and cases and labels are displayed by default in the top-level operators contained in the compound approach , but this is not required . (Β§ 6.4.2 - 6)
  • It is possible to pass to the block , but not in such a way as to bypass declarations with initialization. (Β§ 6.7 - 3)

What you do is technically normal, of course, this does not mean that you should.

+5
source

What you do is completely standard C ++ code, although I don’t think it is particularly easy to read or maintain. If we look at the C ++ standard project section 6.4 Selection Operators, the grammar for the switch statement is as follows:

 switch ( condition ) statement 
Operators

include labels, if, while, for etc ... and section 6.4.2 The switch statement does not create restrictions that might exclude the displayed code.

Case shortcuts are similar to the shortcuts used with goto, which are described in section 6.1 Labeled Designation, but they are limited to use in the switch statement:

Labels and default labels should only be run in switch statements.

and section 6.7 says that we can transfer to a block with some restrictions, such as not bypassing an initialization declaration:

It is possible to pass to the block, but not in such a way as to bypass declarations with initialization. A program that jumps 87 from the point where the variable with the duration of automatic storage is not in the region to the point where it is in the region is poorly formed if the variable is not of a scalar type, class type with trivial default constructor and trivial destructor, cv- a qualified version of one of these types or an array of one of the previous types and is declared without an initializer (8.5).

footnote 87 says:

Passing from the condition of the switch statement to the case label is considered a leap in this regard.

Perhaps one of the most famous and weird uses of the switch statement is to use a Duff device that has a built-in while :

 void send( int *to, const int *from, int count) { int n = (count + 7) / 8; switch(count % 8) { case 0: do { *to = *from++; // <- Scope start case 7: *to = *from++; case 6: *to = *from++; case 5: *to = *from++; case 4: *to = *from++; case 3: *to = *from++; case 2: *to = *from++; case 1: *to = *from++; } while(--n > 0); // <- Scope end } } 
+4
source

All Articles