我一直在想这个问题——为什么不能在switch语句的case标签后面声明变量呢?在c++中,你可以在任何地方声明变量(并且在第一次使用时声明它们显然是一件好事),但以下仍然不能工作:

switch (val)  
{  
case VAL:  
  // This won't work
  int newVal = 42;  
  break;
case ANOTHER_VAL:  
  ...
  break;
}  

上面给了我以下错误(MSC):

'newVal'的初始化被'case'标签跳过

这在其他语言中似乎也是一个限制。为什么这是一个问题?


当前回答

我最喜欢的邪恶切换技巧是使用if(0)跳过不需要的case标签。

switch(val)
{
case 0:
// Do something
if (0) {
case 1:
// Do something else
}
case 2:
// Do something in all cases
}

但非常邪恶。

其他回答

整个switch语句在同一个作用域中。要解决这个问题,可以这样做:

switch (val)
{
    case VAL:
    {
        // This **will** work
        int newVal = 42;
    }
    break;

    case ANOTHER_VAL:
      ...
    break;
}

注意括号。

这个问题的答案是我写的。然而,当我完成它,我发现答案已经关闭。所以我把它贴在这里,也许喜欢参考标准的人会发现它很有用。

问题的原始代码:

int i;
i = 2;
switch(i)
{
    case 1: 
        int k;
        break;
    case 2:
        k = 1;
        cout<<k<<endl;
        break;
}

实际上有两个问题:

1. 为什么我可以在case标签后声明一个变量?

这是因为在c++中标签必须是这样的:

N3337 6.1/1

标记语句: … 属性说明符-seqopt case常量表达式:语句 …

在c++中声明语句也被认为是语句(与C相反):

N3337 6/1:

声明: ... 说明语句 ...

2. 为什么我可以跳过变量声明,然后使用它?

因为: N3337 6.7 / 3

It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps (The transfer from the condition of a switch statement to a case label is considered a jump in this respect.) from a point where a variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has scalar type, class type with a trivial default constructor and a trivial destructor, a cv-qualified version of one of these types, or an array of one of the preceding types and is declared without an initializer (8.5).

因为k是标量类型,并且在声明时没有初始化,跳过它的声明是可能的。这在语义上是等价的:

goto label;

int x;

label:
cout << x << endl;

然而,如果x在声明点初始化,这将是不可能的:

 goto label;

    int x = 58; //error, jumping over declaration with initialization

    label:
    cout << x << endl;

在阅读了所有的答案和更多的研究之后,我得到了一些东西。

Case statements are only 'labels'

在C语言中,根据规范,

§6.8.1标签声明:

labeled-statement:
    identifier : statement
    case constant-expression : statement
    default : statement

在C语言中,没有任何子句允许“标记声明”。这不是语言的一部分。

So

case 1: int x=10;
        printf(" x is %d",x);
break;

这将不会编译,请参阅http://codepad.org/YiyLQTYw。GCC给出一个错误:

label can only be a part of statement and declaration is not a statement

Even

  case 1: int x;
          x=10;
            printf(" x is %d",x);
    break;

这也不是编译,参见http://codepad.org/BXnRD3bu。这里我也得到了同样的错误。


在c++中,根据规范,

允许标记-声明,但不允许标记-初始化。

见http://codepad.org/ZmQ0IyDG。


这种情况的解是二

使用{}使用新的作用域 案例1: { int x = 10; Printf (" x是%d", x); } 打破; 或者使用带标签的虚拟语句 案例1:; int x = 10; Printf (" x是%d",x); 打破; 在switch()之前声明变量,并在case语句中用不同的值初始化它,如果它满足您的要求 main () { int x;//在前面声明 开关(a) { 情况1:x=10; 打破; 情况2:x=20; 打破; } }


还有更多关于switch语句的东西

永远不要在switch中写入任何不属于任何标签的语句,因为它们永远不会被执行:

switch(a)
{
    printf("This will never print"); // This will never executed

    case 1:
        printf(" 1");
        break;

    default:
        break;
}

见http://codepad.org/PA1quYX3。

新变量只能在块范围内声明。你需要这样写:

case VAL:  
  // This will work
  {
  int newVal = 42;  
  }
  break;

当然,newVal只在大括号内有作用域……

干杯,拉尔夫

试试这个:

switch (val)
{
    case VAL:
    {
        int newVal = 42;
    }
    break;
}