118

我看到了这个问题的一些答案,我明白了——你不能在switch. 但我想知道以下在抛出错误时是否正确

错误:“int”之前的预期表达式

代码:

switch (i) {
    case 0:
        int j = 1;
        break;
}

为什么NSLog()在它之前调用不会导致错误?

switch (i) {
    case 0:
        NSLog(@"wtf");
        int j = 1;
        break;
}
4

3 回答 3

146

如果您根据语言的语法进行操作,您实际上可以在 switch 中声明变量。你会得到一个错误,因为 " case 0:" 是一个标签,在 C 中,将声明作为标签后的第一条语句是非法的 - 请注意,编译器需要一个表达式,例如方法调用、正常赋值等。(虽然可能很奇怪,但这就是规则。)

当你把 NSLog() 放在首位时,你就避免了这个限制。您可以将 case 的内容括在 { } 大括号中以引入范围块,或者您可以将变量声明移到 switch 之外。您选择哪个是个人喜好问题。请注意,在 { } 大括号中声明的变量仅在该范围内有效,因此使用它的任何其他代码也必须出现在这些大括号内。


编辑:

顺便说一句,这个怪癖并不像你想象的那么罕见。在 C 和 Java 中,将局部变量声明用作forwhiledo循环,甚至ifelse子句中的单独语句(意思是“不被大括号包围)也是非法的。(事实上,这是包含在“Java Puzzlers”的谜题 #55 中,我强烈推荐。)我认为我们通常不会一开始就写这样的错误,因为在这种情况下将变量声明为唯一的语句是没有意义的。使用switch /但是, case构造,有些人在break 之后省略了大括号语句是控制流的关键语句。

要查看编​​译器是否合适,请将这个可怕的、毫无意义的代码段复制到您的 (Objective-)C 代码中:

if (1)
    int i;
else
    int i;
for (int answer = 1; answer <= 42; answer ++)
    int i;
while (1)
    int i;
do
    int i;
while (1);

总是使用 { } 大括号来分隔此类构造的主体的另一个原因。:-)

于 2009-08-05T04:37:15.970 回答
49

我之前遇到过这个问题,结论是你只是把代码放在一个块里。

switch (i) {
case 0:
    {
        int j = 1;
        break;
    }
}
于 2009-08-05T04:38:05.003 回答
4

我使用的另一个简单解决方法是在声明之前添加一个空表达式(分号)。这避免了将变量范围限制为代码块(或有一些带有代码块的 case 语句和一些没有代码块)。

switch (i) {
    case 0:;
        int j = 1;
        break;
}
于 2013-01-12T20:01:55.917 回答