Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Assume:

switch ( test ) {

  // Set some variables, call some functions ?
  int x = 1 ;
  int y = function(x) ;
  //

  case 1 : 
    // Process for test = 1
    ...
    break;

  case 5 : 
    // Process for test = 5
    ...
    break;

  default : 
    // Process for all other cases.
    ...

}

Is it 'legal' to execute that extra bit of code I added before the first case? I've never seen this in examples.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
232 views
Welcome To Ask or Share your Answers For Others

1 Answer

First some background on how switch (really) works:

A switch is usually thought of as a construct that selects a piece of code to execute depending on the value of some expression, as in

switch (x) {
case 1:
    foo();
    break;

case 2:
    bar();
    break;
}

However, it's more accurate to think of a switch as a form of computed goto statement. For example, the following is perfectly legal:

switch (x) {
    puts("I can't be reached");
case 1:
    if (cond) {
case 2:
        puts("Either x == 1 && cond, or x == 2");
    }
}

Depending on the value of x, the program will jump to either case 1 or case 2 (or past the switch if x is neither 1 nor 2).


Your program will compile as C (with junk values for x and y inside the switch, since the initializations are skipped), but not as C++. The reason is that C++ does not allow a jump to a case label to cross the initialization of a variable. For simple types like int, skipping over int x; is allowed (since no initialization is involved), but not skipping over int x = 1;.

The main motivation for this difference is probably that letting a jump to a case label cross an initialization in C++ would be unsafe when constructors are involved. For example, if C++ allowed a case label to occur after a definition My_class my_object within some scope, then jumping to that case label would skip my_object's constructor but still run its destructor when exiting the scope.

The same restrictions apply to goto in C++. You can't use it to jump into a block and past a variable initialization.


As a side note, switch follows the same general syntax as if and while. The syntax of if as given in the C11 standard (ISO/IEC 9899:2011, section 6.8.4) is

if ( expression ) statement

, while the syntax of switch is

switch ( expression ) statement

The only difference as far as statement is concerned (in C -- C++ adds some more limitations as mentioned above) is that it is allowed to contain case labels (and break) for a switch but not for an if (unless the if occurs within a switch).

Just as with an if, you can even leave off the braces and write code like the following. (Whether this is unnecessarily confusing is another discussion.)

switch (x) case 1: case 2: puts("x is 1 or 2");

Syntactically, case and default labels belong in the same category as goto labels. Section 6.8.1 of the C11 standard has the following definition:

labeled-statement:
        identifier : statement
        case constant-expression : statement
        default : statement


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...