128

I want to jump from the middle of a switch statement, to the loop statement in the following code:

while (something = get_something())
{
    switch (something)
    {
    case A:
    case B:
        break;
    default:
        // get another something and try again
        continue;
    }
    // do something for a handled something
    do_something();
}

Is this a valid way to use continue? Are continue statements ignored by switch statements? Do C and C++ differ on their behaviour here?

Matt Joiner
  • 112,946
  • 110
  • 377
  • 526

6 Answers6

71

It's fine, the continue statement relates to the enclosing loop, and your code should be equivalent to (avoiding such jump statements):

while (something = get_something()) {
    if (something == A || something == B)
        do_something();
}

But if you expect break to exit the loop, as your comment suggest (it always tries again with another something, until it evaluates to false), you'll need a different structure.

For example:

do {
    something = get_something();
} while (!(something == A || something == B));
do_something();
Kerem
  • 11,377
  • 5
  • 59
  • 58
visitor
  • 8,564
  • 2
  • 26
  • 15
  • 2
    'equivalent' only in the semantic sense. the code the compiler generates is very different. with a switch statement, the compiler can generate a jump table which avoids multiple comparisons and thus is much faster than comparing against each element 1 by 1. – chacham15 Feb 11 '14 at 17:11
  • @chacham15, why couldn't the compiler generate the same code for both? – avakar Feb 01 '15 at 18:44
  • @avakar switch statements generate jump tables whereas the other representation is a series of logical evaluations. google jump table for more information. – chacham15 Feb 02 '15 at 04:57
  • @chacham15, what prevents the compiler from generating a jump table for the two if statements or a series of logical evaluations for the switch? – avakar Feb 02 '15 at 21:33
  • 1
    @avakar switch statements require the cases to be constant values, because that is not the case with if statements, it cannot make the same optimization (note: i am speaking in the general case, it is possible given certain requirements (e.g. const values only, only certain logical operators, etc.) to make the optimization, but it is highly compiler dependent and YMMV). – chacham15 Feb 02 '15 at 22:08
36

Yes, continue will be ignored by the switch statement and will go to the condition of the loop to be tested. I'd like to share this extract from The C Programming Language reference by Ritchie:

The continue statement is related to break, but less often used; it causes the next iteration of the enclosing for, while, or do loop to begin. In the while and do, this means that the test part is executed immediately; in the for, control passes to the increment step.

The continue statement applies only to loops, not to a switch statement. A continue inside a switch inside a loop causes the next loop iteration.

I'm not sure about that for C++.

Community
  • 1
  • 1
Islam Elshahat
  • 371
  • 3
  • 3
21

Yes, it's OK - it's just like using it in an if statement. Of course, you can't use a break to break out of a loop from inside a switch.

8

It's syntactically correct and stylistically okay.

Good style requires every case: statement should end with one of the following:

 break;
 continue;
 return (x);
 exit (x);
 throw (x);
 //fallthrough

Additionally, following case (x): immediately with

 case (y):
 default:

is permissible - bundling several cases that have exactly the same effect.

Anything else is suspected to be a mistake, just like if(a=4){...} Of course you need enclosing loop (while, for, do...while) for continue to work. It won't loop back to case() alone. But a construct like:

while(record = getNewRecord())
{
    switch(record.type)
    {
        case RECORD_TYPE_...;
            ...
        break;
        default: //unknown type
            continue; //skip processing this record altogether.
    }
    //...more processing...
}

...is okay.

SF.
  • 13,549
  • 14
  • 71
  • 107
  • 3
    sorry for necroposting, but I would add that a call to `exit` would also usually be a fine thing to end a switch case with. – Vality Dec 29 '14 at 10:04
  • 1
    Well, I am going to got all *Dr. Frankenstein* here and also point out that `default:` does not have to be the last/bottom entry - as [this](https://stackoverflow.com/q/3110088/4805858) question points out... – SlySven Dec 07 '18 at 01:41
  • 1
    @SlySven: Lexically, it doesn't, but if you don't have a good reason not to make it last, do make it last. It's often confusing if used at other places. – SF. Dec 07 '18 at 08:51
  • 2
    @SF. well, I can easily imagine the cases when it would make more sense to make `default:` case the first instead of the last. Like "do this, unless you get the following unusual values, which should be handled as follows". – Ruslan Jul 09 '20 at 12:37
6

While technically valid, all these jumps obscure control flow -- especially the continue statement.

I would use such a trick as a last resort, not first one.

How about

while (something = get_something())
{
    switch (something)
    {
    case A:
    case B:
        do_something();
    }        
}

It's shorter and perform its stuff in a more clear way.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alexander Poluektov
  • 7,844
  • 1
  • 28
  • 32
  • 1
    sorry for the confusion Alexander, the code is for demonstration only, i have good reason (i believe) for the actual structure in my code. – Matt Joiner Jan 27 '10 at 12:40
  • 2
    @Matt: That would probably mean an even more obfuscated structure... :) – visitor Jan 27 '10 at 12:43
-5

Switch is not considered as loop so you cannot use Continue inside a case statement in switch...

  • 7
    The `switch` statement is inside a `while` loop, so `continue` is perfectly valid. – Rick Jul 26 '17 at 19:41