tags:

views:

28

answers:

4

I just read this question: http://stackoverflow.com/questions/3585073/why-are-different-case-condition-bodies-not-in-different-scope

It's a Java question, but my question applies to both C# and Java (and any other language with this scope reducing feature).

In the question, OP talks about how he knows he can manually add in {} to refine the scope of each case in the switch. My question is, how does this work? Does it go up the stack as if it were a method call? If so, what does it do so that it still have access to other variables declared before this scope?

+3  A: 

All it's doing is defining another scope, it's not translated into a method call. Remember that for locals, the CLR/JVM could decide not to use stack space for them at all, it could choose to utilise processor registers. In some cases, if you'll excuse the pun, it could decide to optimise out some of the locals by virtue of them not being needed. It could even decide that it can use one register, or memory location "on the stack" for multiple variables as they're never going to overlap.

Taking the example from the linked question:

switch(condition) {
  case CONDITION_ONE: {
    int account = 27373;
  }
  case CONDITION_TWO: {
    // account var not needed here
  }
  case CONDITION_THREE: {
    // account var not needed here
  }
  case CONDITION_FOUR: {
    int account = 90384;
  }
}

As it stands, that code is functionally identical to:

int account;

switch(condition) {
  case CONDITION_ONE: {
    account = 27373;
  }
  case CONDITION_TWO: {
    // account var not needed here
  }
  case CONDITION_THREE: {
    // account var not needed here
  }
  case CONDITION_FOUR: {
    account = 90384;
  }
}

As the account variable is never used in multiple cases, which means it's an ideal candidate (in this simplistic example ) for using a register or a single space in memory.

Rob
+2  A: 

Scope is defined by the compiler at compile time. It has little effect on the actually memory layout of the variables. Hence if I were to write:

func()
{ 
    int a;
    {
      int b;
    }
    {
      int c;
    }
}

The compiler may choose to create three variables, and allocate space for all three at the start of the function or it may just allocate space for two variables, and use the same space for b & c.

Scope is just so the compiler knows when a variable is no longer needed. Exactly what it does with that information is it's business.

James Curran
@James, you've typo'd `variables` in your last two sentences - I haven't corrected it incase you're adding to your answer at the moment and our edits overlap =) (Plus I think it's poor etiquette to edit someones answer until you're sure they've finished with it!) (*Edit: Remove typo from the word sentence* **sigh**)
Rob
So, I had a 25% success rate in spelling that word (actually I probably misspelled it the fourth time too, but I jsut caught that one myself...)
James Curran
I'd best not mention the fact that you've pluralised `variable` in your penultimate sentence then... ;-) Oh, and +1 from me for your answer =)
Rob
D'oh -- I copy'n'Pasted it to avoid future typos... That didn't work out.. (and I've already hit the daily limit -- I need *accepted* answers now...;-)
James Curran
+1  A: 

My question is, how does this work? Does it go up the stack as if it were a method call?

It works just like any other pair of {} used to create a new local scope. There's no difference scopewise between this:

void foo() {
    {
        int a = 123;
    }
    // a is gone here
    {
        // different a
        float a = 12.3f;
    }
}

and this:

void foo() {
    switch (123) {
    case 1:
        {
            int a = 123;
        }
        // a is gone here
        break;

    case 2:
        {
            // different a
            float a = 12.3f;
        }
    }
}

If so, what does it do so that it still have access to other variables declared before this scope?

Blocks always have access to their outer scopes or this wouldn't work:

void foo() {
    int a = 123;
    if (true) {
        a = 345; // accessing a in outer scope
    }
}
munificent
Ah, in the second part of your answer, the one about variables declared before the scope. I should have thought about that, but I was busy thinking about it faking a method. I really overcomplicated this question when I was thinking about it.
Corey Ogburn
A: 

Any variables declared inside a scope can only be accessed within that scope and any scopes inside it. So in a function, you could use {} in many programming languages to create variables that would be destructed when leaving that scope.

Also, problems can occur when using switch and not using scopes, as demonstrated by this little piece of C code:

int main() {
  int foo = 4;
  int bar = getbar(); // getbar() is a function returning an integer
  switch(bar)
  {
    case 1:
      int abc = 6;
      break;
    case 2:
      int abc = 7; // compiler error: 'abc' was defined twice in this scope
      break;
  }
}
int abc = 147; // This is no error, as 'abc' fell out of scope when
// leaving the `switch` statement

As you can see, abc has been declared twice in the scope of the switch, and that results in an error. This would easily have been fixed to giving each case its own variable scope:

int main() {
  int foo = 4;
  int bar = getbar(); // getbar() is a function returning an integer
  switch(bar)
  {
    case 1:
    {
      int abc = 6;
      break;
    }
    case 2:
    {
      int abc = 7; // no more errors, since these declarations will destruct when
      // falling out of scope
      break;
    }
  }
}
int abc = 147; // This is no error, as 'abc' fell out of scope when
// leaving the `switch` statement
Frxstrem