2010-08-27 92 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