Thread: Switch case variable scope

  1. #1
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607

    Switch case variable scope

    Ran into something today that does not make sense:

    This compiles:
    Code:
    int x = 5;
    
    switch(x)
    {
        case 0:
        {
             int value = 5;
        }
        break;
        
        case 1:
        {
             int value = 6;
        }
        break;
    }
    This does not:
    Code:
    int x = 5;
    
    switch(x)
    {
        case 0:
        {
             int value = 5;
        }
        break;
        
        case 1:
             int value = 6;
             break;
    }
    Ok so it doesn't like int value = 6 b/c of int value = 5 for case 0. However since the value in case 0 is declared within the brackets one would think it has case scope.

    So I tried this:
    Code:
    int x = 5;
    
    switch(x)
    {
        case 0:
        {
            int value = 5;
        }
        break;
    
        case 1:
             value = 6;
             break;
    }
    Now it doesn't like it b/c value has not been declared in case 1:. These two conditions cannot possibly be both true at the same time. You cannot disallow the declaration of value in case 1 b/c it interferes with value in case 0 and at the same time disallow me to use value from case 0 b/c it is not in scope. If it was not in scope then theoretically I should be able to declare value in case 1.

    Both MSVS 2012 and 2013 exhibit the same behavior. I checked the standard and it is unclear on the matter.

    Any explanations?
    Last edited by VirtualAce; 01-31-2014 at 04:57 PM.

  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    C or C++?

    *shrug*

    Several possibilities depending on language, how "Visual C++" parses expressions, and which example.

    The most likely explanation:

    1): You can't jump over declarations having assignments in C++.* (The scope from the `case' is different than the scope of the `switch'.)
    2): You can't implicitly declare variables in C++.

    Soma

    *): From what I recall, some stuff may be related to "dumb" variables, but "Visual C++" may not honor that in any event.
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Uh...its for C#.

  4. #4
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Uh...its for C#.
    O_o

    Sorry, I had just been reading "techboard".

    *shrug*

    [Edit]
    Actually, I've never looked at C#5 so this behavior may have changed.

    Of course, I only really ever tried C#2 for any real project so it also may have changed and I just didn't notice.
    [/Edit]

    I imagine this is born of C# having broken "shadowing" rules.

    In other words, you probably got it wrong in the second example; the compiler probably see `int value = 6;' as local to the `switch' so `int value = 5' "shadows" the `6' version.

    Yeah, the "shadowing" works differently in `switch' than it does in other cases.

    [Edit]
    Code:
    int x = 5;
     
    switch(x)
    {
        case 0:
        {
             int value = 5;
        }
        break;
         
        case 1:
        {
             int value = 6;
        }
        break;
    }
    --or--
    Code:
    int x = 5;
     
    switch(x)
    {
        case 0:
             int value = 5;
        break;
         
        case 1:
             value = 6;
        break;
    }
    [/Edit]

    Soma
    Last edited by phantomotap; 01-31-2014 at 05:58 PM.
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  5. #5
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Well it seems broken. Theoretically if braces denote scope then the variable inside of them should have scope limited to the braces. The fact that I cannot declare a variable with the same name and type in other case statements even though the variable is declared in another scope in another case makes me think that braces are not denoting scope in switch statements. But then if you use braces on both statements it works which seems odd. So it seems the variables in a case statement have switch scope (as the standard states) even if it is within braces...which then seems to break the fundamental rule that braces denote scope. But you can't then turn around and say variables within braces within case statements have case scope if and only if all variables are declared within braces in separate case statements.

    Something seems broken about it all.

  6. #6
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    It's because of a how C# scope and switch statements work:

    1. Unless you use brackets, the scope of a variable in a switch statement is the entire body of the switch statement.

    2. In general, you cannot have the same variable used in a nested scope and its parent's scope (with a few exceptions). This is essentially what your second example is - the variable being defined both in the switch scope and the case scope.

    The following is also not allowed, and it's basically what you're doing:

    Code:
    void foo()
    {
          {
                int i = 2;
          }
          int i = 1;
    }
    Last edited by Cat; 01-31-2014 at 10:55 PM.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  7. #7
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Quote Originally Posted by phantomotap View Post
    I imagine this is born of C# having broken "shadowing" rules.
    I wouldn't really say "broken". C# is much stricter about the circumstances in which you can shadow variables as a deliberate design decision.

    Essentially, you can shadow a class member within a class method, and you can shadow an outer class member within an inner class member, but most other cases of variable shadowing are forbidden. Even in cases where you CAN shadow, there are restrictions that you can't use the same unqualified name to refer to two entities in the same declaration space. For example, this doesn't work:

    Code:
    class foo
    {
         private int x;
         void bar()
         {
              x = 5;  // To compile, you must use this.x = 5; instead
              // ...
              int x;
              x = 10;
         }
    }
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  8. #8
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    I wouldn't really say "broken". C# is much stricter about the circumstances in which you can shadow variables as a deliberate design decision.
    O_o

    Yeah, well, it is broken, and the thing is broken because C# isn't much stricter; C# is only inconsistent.

    If C# didn't allow any "shadowing", I'd be on the same page with "much stricter", but as is, the inconsistency just makes the allowed occasions surprising to some and the disallowed occasions surprising to others.

    Yeah, it is a quality of implementation issue, but I have tools here to error on "shadowing" for C, C++, Javascript, and Python. C# should have just went the sane route and disallowed it altogether.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Switch Case
    By KMAN999 in forum C Programming
    Replies: 2
    Last Post: 06-27-2011, 07:28 PM
  2. Replies: 8
    Last Post: 02-14-2010, 04:14 PM
  3. Replies: 11
    Last Post: 08-25-2008, 12:01 PM
  4. declare a variable in a case/switch?
    By Oluf in forum Windows Programming
    Replies: 2
    Last Post: 12-13-2003, 01:39 PM
  5. switch case
    By threahdead in forum C Programming
    Replies: 5
    Last Post: 09-30-2002, 02:37 PM