Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is case statement allowed inside block for another case? [duplicate]

I've ran across code that looks like this:

  switch(i) {
    case 2: {
      std::cout << "2";
      break;
    case 3:
      std::cout << "3";
      break;
    }
    case 4: {
      std::cout << "4";
      break;
    }    
  }

Notice that case 2 opens a block with curly brace, which is closed only after case 3. At first this seemed like a typo that would either cause a compiler error, or, even worse, ignore case 3. But it works just fine in c++ and outputs 3 if i is 3. I come from java background so my understanding of logical blocks in c++ may be lacking. So my question is: is this deliberate behavior?

like image 894
Denis Tulskiy Avatar asked Feb 06 '17 22:02

Denis Tulskiy


People also ask

Can we write if if else else if inside case block?

Yes, and just like that.

Can we have multiple statements in a single case block?

Also, you can write multiple statements in a case without using curly braces { }. As per the above syntax, switch statement contains an expression or literal value. An expression will return a value when evaluated. The switch can includes multiple cases where each case represents a particular value.

Can switch case have duplicates?

If two cases in a 'switch' statement are identical, the second case will never be executed. This most likely indicates a copy-paste error where the first case was copied and then not properly adjusted.

Can you put a case inside a case C++?

you can say a case inside case without its switch or preceded by a break will work the same way a label works.


Video Answer


2 Answers

You can, but shouldn't, abuse case labels in a switch far worse than that — and far worse than Duff's Device. Duff's Device has the dubious privilege of being almost plausibly useful and yet can be regarded as abusing switch.

Not all abuses of switch can claim to be plausibly useful. For instance, this compiles as C or C++, even with stringent warnings set:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char **argv)
{
    unsigned seed;
    if (argc == 2)
        seed = atoi(argv[1]);
    else
        seed = time(0);
    printf("seed: %u\n", seed);
    srand(seed);

    int i = rand() % 10;
    int j = 21;
    int k = 37;
    printf("i: %d\n", i);
    switch (i)
    {
    case 1:
        for (j = 10; j > i; j--)
        {
        case 2:
            printf("case 2:\n");
            for (k = j - 1; k > 0; k--)
            {
            case 6:
                printf("case 6:\n");
            default:
                printf("%d-%d-%d\n", i, j, k);
            }
        case 5:
            printf("case 5:\n");
            printf("%d-%d\n", i, j);
            break;
        }
        break;
    case 3:
        printf("case 3:\n");
        break;
    }
    return 0;
}

The argument handling allows you set the seed, so you can reproduce results if you want to. I'd make no claim that it is useful; indeed, it is not useful. Note that break inside the loops breaks the loop, not the switch.

Basically, case labels (and default) must be within the scope of a switch, and are associated with the innermost enclosing switch. There are few other constraints on them. You have to be careful not to jump over variable initializations, etc (that's why j and k are defined outside the switch()). But otherwise, they're just labels, and control will flow to them when 'appropriate'.

like image 111
Jonathan Leffler Avatar answered Oct 27 '22 00:10

Jonathan Leffler


switch statement in C/C++ is a glorified goto statement (with some optimization benefits).

As a result, you can do as much with case labels as you'd do with goto labels. In particular, jumping inside the block is allowed, as long as you are not bypassing any variable initialization.

like image 33
SergeyA Avatar answered Oct 26 '22 23:10

SergeyA