2

I have the following switch with a break without a case :

char c = 'a';
switch(c) {
    break;
    case 'a' : cout << 'a' << endl;
    break;
    case 'b' : cout << 'b' << endl;
    break;
    default : break;
}

Why does this code snippet print a? Shoudn't the switch break after encountering the first break statement only?

Jarvis
  • 8,494
  • 3
  • 27
  • 58
  • 1
    `switch` and `break` doesn't work like that (as you noticed). Statements not in `case` labels are simply disregarded. – Some programmer dude Jan 27 '20 at 11:47
  • 1
    No, why? In switch you enter the code once appropriate case is encountered. Else default is trigerred. Why would that case-less break be even considered? It should be a warning when case-less code is in switch, tho. – ALX23z Jan 27 '20 at 11:47
  • fwiw, i was expecting that this can be answered by reading https://en.cppreference.com/w/cpp/language/break, though after reading that one can still believe that your code does what you expect... – 463035818_is_not_an_ai Jan 27 '20 at 12:06

4 Answers4

4

The first break is ignored.

At switch(c), the runtime jumps to case 'a' as c=='a'. Everything before that is ignored.

This is why case 'b' works without printing 'a', and this is why variable definitions are frowned upon in switch blocks:

int n=0;
switch (n)
{
    int k=n;
case 0:
    return k; // UB
}
YSC
  • 38,212
  • 9
  • 96
  • 149
  • It seems to be ill-formed, not UB. I get `error: cannot jump from switch statement to this case label` `note: jump bypasses variable initialization`. – HolyBlackCat Jan 27 '20 at 11:52
  • @HolyBlackCat I _think_ this is UB but all major compilers are nice enough to raise an error; I see no mention of variables having different lifetime in `switch` blocks: http://eel.is/c++draft/stmt.switch – YSC Jan 27 '20 at 11:55
  • Also, nothing about `switch` here: http://eel.is/c++draft/basic.lookup – YSC Jan 27 '20 at 11:56
  • Hmm. I asked [a question](https://stackoverflow.com/questions/59931168/is-jumping-over-a-variable-initialization-ill-formed-or-causes-ub) about it. – HolyBlackCat Jan 27 '20 at 12:26
1

In C, a case inside a switch is (analogous to) a goto label. The head of the switch is analogous to the goto itself.

Consequences

  • break must in general be used because the "switch-in" is goto-based ie not structured or single point of entry&exit
  • Any statement before the first case is never reached
  • Famous usage Duffs Device
Community
  • 1
  • 1
Rusi
  • 1,054
  • 10
  • 21
1

A switch is a compact and readable form of what could be a series of ugly ifs and gotos otherwise:

char c = 'a';
if(c=='a')goto _a;         // test for "case 'a':"
if(c=='b')goto _b;         // test for "case 'b':"
goto _default;             // unconditional jump to "default:"
goto _break;               // <-- program never goes to this line, the one you are asking about
_a: cout << 'a' << endl;
goto _break;
_b: cout << 'b' << endl;
goto _break;
_default:
goto _break;
_break:

Test: https://ideone.com/OgsQuT

tevemadar
  • 12,389
  • 3
  • 21
  • 49
0

From cppreference:

If condition evaluates to the value that is equal to the value of one of constant_expressions, then control is transferred to the statement that is labeled with that constant_expression.

If condition evaluates to the value that doesn't match any of the case: labels, and the default: label is present, control is transferred to the statement labeled with the default: label.

The switch works as if there was a goto from the condition to the cases, hence your break is never executed. More generally anything you put there is dead code:

switch(1) {
    foo();                // dead code !
    case 1 : cout << '1'; // prints "1"
         break;       // and exits the switch
    case 2 : cout << '2';
         break;
}
Community
  • 1
  • 1
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185