2010-08-27 72 views
1

我刚读了这个问题:Why are different case condition bodies not in different scope?范围定义括号和堆栈?

这是一个Java的问题,但我的问题适用于C#和Java(以及任何其他语言与此范围内降低功能)。

在的问题,他是如何知道他可以在{}手动添加到细化的交换机的每个案件范围OP会谈。我的问题是,这是如何工作的?它是否像方法调用一样上升?如果是这样,它做了什么以便它仍然可以访问此范围之前声明的其他变量?

回答

3

所有它做的是另一种定义范围,它不翻译成方法调用。请记住,对于本地人来说,CLR/JVM可以决定不使用堆栈空间,它可以选择使用处理器寄存器。在某些情况下,如果你能够原谅双关语,它可以决定优化一些当地人,因为他们不需要。它甚至可以决定它可以使用一个寄存器或“堆栈中”的内存位置来存放多个变量,因为它们永远不会重叠。

以从链接的问题的例子:

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; 
    } 
} 

既然这样,该代码是功能上等同于:

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; 
    } 
} 

作为account变量从未在多个的情况下使用,这意味着它是一个理想的候选者(在这个简单的例子中)在内存中使用寄存器或单个空间。

2

作用域在编译时由编译器定义。它对变量的实际内存布局几乎没有影响。因此,如果我写:

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

编译器可以选择创建三个变量,并在函数的开始分配所有三个空间,或者它可能只是分配空间两个变量,并使用相同的空间对于b & c。

范围就是这么当变量不再需要编译器知道。这些信息的确切含义是业务。

+0

你在最后两句话已经typo'd'variables' - 柜面你添加到你的答案,我还没有纠正它目前和我们的编辑重叠=)(另外我认为编辑某人的答案是很糟糕的礼节,直到你确定他们已经完成了它!)(*编辑:从单词句子* **叹息**中删除错字) – Rob 2010-08-27 15:43:26

+2

所以,我拼写这个单词的成功率为25%(实际上我可能第四次拼错了它,但我只是自己抓到了那个...) – 2010-08-27 15:46:19

+0

我最好不要提到你已经复数化的事实你的倒数第二句话中的“variable”,然后...... ;-)哦,和我+1的答案=) – Rob 2010-08-27 15:48:43

1

我的问题是,如何工作的呢?它是否像方法调用一样上升?

它和其他用于创建新本地作用域的{}对一样工作。有此之间没有区别scopewise:和

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

这样的:

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

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

如果是的话,它有什么作用,使其仍然可以访问这个范围之前声明的其他变量?

块总是可以访问其外部范围或这是行不通的:

void foo() { 
    int a = 123; 
    if (true) { 
     a = 345; // accessing a in outer scope 
    } 
} 
+0

啊,在你的第二部分答案,关于在范围之前声明的变量的答案。我应该想到这一点,但我一直在想它伪造一种方法。当我想到这个问题时,我真的太过于复杂了。 – 2010-08-27 15:49:38

0

一个范围内声明的任何变量只能在该范围和它里面的任何范围内进行访问。因此,在一个函数中,您可以在许多编程语言中使用{}来创建在离开该范围时将被破坏的变量。

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 

正如你所看到的,abc已经在switch的范围内声明的两倍:

此外,使用switch和不使用范围时,通过这个小片的C代码为证明可能出现的问题,并导致错误。这很容易被固定给每个case自己的变量范围:

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