簡體   English   中英

開關盒中的局部范圍

[英]local scope in switch case

我看到了一些令人驚訝的代碼:

#include <iostream>
using namespace std;

int main() {
    // your code goes here
    auto myDummy = [](int i){
    switch(i){
        case 0: return 0;
        case 1:{
            std::cout << "Evaluated 1\n";
            if(i == 1){
                return 1;
            }
            case 2:
            std::cout << "Evaluated 2\n";
            return 2;
        }
        break;
        default: return -1;
    }
    };
    std::cout << myDummy(1) << "\n";
    return 0;
}

它在沒有警告的情況下編譯和運行。 案例1 {}的括號似乎被忽略了。

myDummy(1)

- > 1

myDummy(2)

- > 2

如果我將案例1的代碼修改為:

             case 1:{
                std::cout << "Evaluated 1\n";
                int a = i;
                if(a == 1){
                    return 1;
                }
                case 2:
                std::cout << "Evaluated 2\n";
                return 2;
            }
            break;

然后它不再編譯:

prog.cpp:16:13:錯誤:跳轉到案例標簽[-fpermissive]

  case 2: ^ prog.cpp:12:21: note: crosses initialization of 'int a' int a = i; 

案例1的括號:{}中斷; 不要取消開關上下文。 它只是為變量創建了一個局部范圍。 但這真的很混亂。 為什么這樣的行為呢?

這是標准關於switch說法(§6.4.2,強調我的):

2 - switch語句中的任何語句都可以用一個或多個case標簽標記,如下所示:case constant-expression:其中constant-expression應該是switch類型的switch類型的轉換常量表達式(5.19)。

<...>

5 - 執行switch語句時,將評估其條件並與每個case常量進行比較。 如果其中一個case常量等於條件的值,則將控制權傳遞給匹配的case標簽后面的語句

因此, switch並不關心具體情況,以下是有效的:

int main() {
    int i = 0;
    switch(i)
    {
        case 1:
        {
        case 2:
            {
                if(false)
                {
                    case 0:
                        std::cout << "hello there!"; //yes it will print
                }
            }
        }
    }

    return 0;
}

關於你提出的修改,請檢查我對這個問題的回答 基本上用

case 1:{
    std::cout << "Evaluated 1\n";
    int a = i;
    if(a == 1){
            return 1;
    }
    case 2:
    //here a is in scope
    std::cout << "Evaluated 2\n";
    return 2;
 }

您可以跳轉到case2而不真正創建a ,但a仍然會在范圍內。

您可以在任何地方放置范圍:

int main() {
    int a;
    {
        int a; // in a more local scope.
    }
}

但是你不能在一個范圍內放置一個變量初始化,它可以被超過2個開關的情況看到:

int main() {
    int b;
    switch(1) {
    case 0:
        int a = 0; // error
        break;
    case 1:
        b = a; // what happens?
        break;
    }
}

最后,在另一個范圍內的案例標簽沒有任何問題(只要它不違反我們的第二個規則,那里):

int main() {
  switch(1) {
  case 1: {
    break;
  case 2:
    break;
    }
  }
}

switch到標簽的工作方式與移動到不同范圍塊時goto標簽的方式相同。

在采用這樣的方案時應該小心,特別是在讀取未初始化的變量時,其行為是未定義的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM