在switch case语句中初始化数组

时间:2016-02-03 12:35:35

标签: c++ c arrays initialization switch-statement

奇怪的是,我在一个switch语句中初始化了以下数组c,完全期望我的编译器说 NO你不能那样做但令我惊讶的是它编译在MSVC,GCC中和Clang。在线{{3}}

我假设标准允许它,在这种情况下我的问题是为什么? ...考虑到case语句中不允许声明和初始化非数组。

int main()
{
    char ch;

    switch( ch )
    {
    case 'x':
        //int a = 42; // NOT OKAY
        break;

    case 'y':
        int b;
        b = 42;    // OKAY

    case 'z':
        int c[2] = { 0 , 1 };  // OKAY (Huh???)
        break;
    };
}

3 个答案:

答案 0 :(得分:6)

如果您将示例更改为

int main()
{
    char ch;

    switch( ch )
    {
    case 'x':
        int c[2] = { 0 , 1 };
        break;

    case 'z':
        int a = 42;
        break;
    }
}

你会注意到数组现在出现了错误,但int却没有。

最后一种情况实际上允许使用初始化。

规则不是“你不允许在case中初始化变量”,而是“你不允许跳过变量初始化。”

在最后一种情况下,跳过初始化是不可能的。

规则的原因是在case中声明的变量在后续情况下属于范围,跳转到后续情况会绕过初始化。

如果你重写为goto序列,这会变得(略微)更清晰,因为关于范围和初始化的相同规则适用:

if (ch == 'x') goto x;
if (ch == 'y') goto y;
if (ch == 'z') goto z;
goto end;
{
  x:
    int a = 42;  // goto y or z breaks this
    goto end;
  y:
    int b;      // uninitialised, so OK
    b = 42;
    goto end;
  z:
    int c[2] = {0, 1};  // No label after this, so can't jump across, so OK
    goto end;
}
end:

答案 1 :(得分:2)

如果跳转到case标签绕过初始化的数组,编译器将发出错误。例如

    switch( ch )
    {
        int c[2] = { 0 , 1 };  // OKAY (Huh???)
    case 'x':
        //int a = 42; // NOT OKAY
        break;

    case 'y':
        int b;
        b = 42;    // OKAY

    case 'z':
//        int c[2] = { 0 , 1 };  // OKAY (Huh???)
        break;
    } 

    switch( ch )
    {
    case 'x':
        //int a = 42; // NOT OKAY
        break;

    case 'y':
        int b;
        b = 42;    // OKAY

    case 'z':
        int c[2] = { 0 , 1 };  // OKAY (Huh???)
        break;
    default:
        break;
    } 

但是在原始程序中,两个跳转都不会绕过初始化的数组。

这是一个更简化的示范程序。 这将成功编译

int main() 
{
    goto L1;

    {
        L1:;
        int c[2] = { 0 , 1 };
    }       
}    

虽然这会发出错误

int main() 
{
    goto L1;

    {
        int c[2] = { 0 , 1 };
        L1:;
    }       
}    

答案 2 :(得分:0)

你的阵列完全没问题。您在switch(ch)的词法范围内声明(并初始化)它,允许它存在,被初始化,并被其他操作引用(在声明之后)。

switch之外引用它的行为是不可行的,如下所示:

switch(ch) {
  ...
  case 'z':
    int c[2] = { 0 , 1 };  // OKAY (Huh???)
    break;
};

some_operation(c);

如果您使用另一个使用相同变量的 case语句,则禁止此操作的唯一情况是。由于case语句只是标签(如指出here),因此您可能只是跳过后续使用变量的初始化。

所以,只要你只在一个标签中使用变量,编译器就可以这样做,但不是多个。