Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

local scope in switch case

Tags:

c++

I saw some surprising code:

#include <iostream>
using namespace std;

int main() {
    // your code goes here
    auto myDummy = [](int i){
    switch(i){
        case 0: return 0;
        case 1:{
            std::cout << "Evaluated 1\n";
            if(i == 1){
                return 1;
            }
            case 2:
            std::cout << "Evaluated 2\n";
            return 2;
        }
        break;
        default: return -1;
    }
    };
    std::cout << myDummy(1) << "\n";
    return 0;
}

It compiles and run without warning. The bracket of case 1{} seems to be ignored.

myDummy(1)

-> 1

myDummy(2)

-> 2

If I modify the code for case 1 to be:

             case 1:{
                std::cout << "Evaluated 1\n";
                int a = i;
                if(a == 1){
                    return 1;
                }
                case 2:
                std::cout << "Evaluated 2\n";
                return 2;
            }
            break;

then it does not compile anymore:

prog.cpp:16:13: error: jump to case label [-fpermissive]

    case 2:

         ^ prog.cpp:12:21: note:   crosses initialization of 'int a'

             int a = i;

The brackets for case 1:{}break; do not cancel the switch context. It just creates a local scope for variable. But this is really obfuscating. Why such a behaviour?

like image 264
Darius Zu CH Avatar asked Feb 09 '23 18:02

Darius Zu CH


2 Answers

Here's what the standard says about a switch (§6.4.2, emphasis mine):

2 - Any statement within the switch statement can be labeled with one or more case labels as follows: case constant-expression : where the constant-expression shall be a converted constant expression ( 5.19 ) of the promoted type of the switch condition.

<...>

5 - When the switch statement is executed, its condition is evaluated and compared with each case constant. If one of the case constants is equal to the value of the condition, control is passed to the statement following the matched case label

So the switch doesn't care where exactly the cases are, the following works:

int main() {
    int i = 0;
    switch(i)
    {
        case 1:
        {
        case 2:
            {
                if(false)
                {
                    case 0:
                        std::cout << "hello there!"; //yes it will print
                }
            }
        }
    }

    return 0;
}

Regarding the modification you propose, check my answer to this question. Basically with

case 1:{
    std::cout << "Evaluated 1\n";
    int a = i;
    if(a == 1){
            return 1;
    }
    case 2:
    //here a is in scope
    std::cout << "Evaluated 2\n";
    return 2;
 }

you can jump to case2 without actually creating a, but a will still be in scope.

like image 145
SingerOfTheFall Avatar answered Feb 11 '23 07:02

SingerOfTheFall


switch to a label works in an identical way to goto with a label when it comes to moving to a different scope block.

You should take care when adopting such a scheme, in particular with regards to reading uninitialised variables, the behaviour of which is undefined.

like image 40
Bathsheba Avatar answered Feb 11 '23 07:02

Bathsheba