9

Why does this code fragment run fine

void foo(int i)
{
    switch(i) {
    case 1:
    {
        X x1;
        break;
    }
    case 2:
        X x2;
        break;
    }
}

whereas the following gives compilation error (initialization of 'x1' is skipped by 'case' label)?

void foo(int i)
{
    switch(i) {
    case 1:
        X x1;
        break;
    case 2:
        X x2;
        break;
    }
}

I understand that using braces introduces a new scope, hence storage will not be allocated for x1 till we hit its opening brace. But x2 is still initialized inside a case label without enclosing braces. Should this not be an error too?

I think initialization of x2 can be conditionally skipped in both the code fragments

patentfox
  • 1,436
  • 2
  • 13
  • 28

5 Answers5

7

1: Valid

 case 1:
        {
        X x1;
        break;
        }

If it doesn't hit the condition, x1 can't be used by any further statements, so there can't be a runtime error with this. x1 doesn't try to exist outside braces.


2: Invalid

 switch(i) {
    case 1:
        X x1; //don't break
        i = 2;
        ...
        ...
        ...
     case 2:
        x1.someOperation()

 }

In the above, if i was 2 initially, you'd hit x1.someOperation() before X x1 which would construct the object.

If it was allowed to compile, it would throw a runtime error or not, depending upon whether the case:1 was executed before 2, (and the object was constructed). Hence, it is disallowed by the compiler.


The same is allowed with Plain Old Data types which cannot have a user-defined constructor.

Anirudh Ramanathan
  • 46,179
  • 22
  • 132
  • 191
4

Note that you will get error only when X is a non-POD. If X is POD, then you will not get any error (when you don't use braces).

In case of non-POD, you cannot skip initialization of variables which are declared in the same scope. It results in compilation error when you don't use braces, because the switch lets you skip the initialization of such variables, yet at the same time it made them available to be used in all the case labels below it. That is dangerous.

Think along this line : if i is 2 , then the control will jump to the second case directly without initializing x1, and then you will be able to use x1 in the second case even though it is not initialized. That doesn't make sense. Therefore, the language requires it to be an error.


By the way, to know what POD and non-POD is, see these topics:

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • @GrijeshChauhan: See my answer. I added two links. – Nawaz Nov 16 '12 at 11:49
  • Nawaz :- Add full-form of POD , I can't understand error! look here http://codepad.org/ILDmG4Z9 – Grijesh Chauhan Nov 16 '12 at 11:52
  • @GrijeshChauhan: POD means Plain Old Datatype. Please go through the links provided in my answer. POD is a well-known abbreviation in C++. Also, the code which you posted at codepad is compiled as C which is a different language. If you compile it as C++, it will compile fine, because that is a valid code. See this : http://codepad.org/DOGUwa9d – Nawaz Nov 16 '12 at 11:56
  • 1
    @Nawaz thanks for this answer - it's amazing sometimes how little I know - this helped me a lot. – Caribou Nov 16 '12 at 12:09
  • 1
    @Nawaz: WaW! Excellent..I was unaware of this!...Thanks Nawaz – Grijesh Chauhan Nov 16 '12 at 18:19
  • @Nawaz : Hi Nawaz - I saw your profile, linkedIn's also..You are interested in algorithm. Will please check my answer here. http://stackoverflow.com/questions/13410763/print-numbers-in-ascending-order-from-an-n-x-m-array-whose-rows-are-sorted/13411529#13411529 – Grijesh Chauhan Nov 16 '12 at 18:57
2

The general idea is that each case is not a isolated scope: the code under case 2 could refer the x1 variable, since it has been declared before in the same scope (i.e.: the entire switch block): of course, it would not have been initialized, and it would result in an error.

Adding curly brackets you are actually splitting each case's scope, allowing you to declare variables in case 1 that can not be referred outside of it.

Coffee on Mars
  • 988
  • 6
  • 21
0

It's not a good idea to create variables inside conditional statements. I recommend you to create the variable outside the switch statement and then asign values to it according with the condition on i:

void foo(int i) {

    X x1;

    switch(i) {
        case 1:
            x1 = ...;
            break;
        case 2:
            x1 = ...;
            break;
    }
}
adripanico
  • 1,026
  • 14
  • 32
0

In the version that fails, the declaration of x1 doesn't go out of scope until several lines after the case 2: label. That's the problem. The declaration of x2 is okay because there's no case label between the declaration and the end of its scope.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165