【问题标题】:Can I declare variables inside an Objective-C switch statement?我可以在 Objective-C switch 语句中声明变量吗?
【发布时间】:2010-11-10 01:27:38
【问题描述】:

我想我要瞎了,因为我不知道这段代码中的语法错误在哪里:

if( cell == nil ) {
    titledCell = [ [ [ TitledCell alloc ] initWithFrame:CGRectZero
        reuseIdentifier:CellIdentifier ] autorelease
    ];

    switch( cellNumber ) {
        case 1:
            NSString *viewDataKey = @"Name";
etc...

当我尝试编译它时,我得到一个 Error: syntax error before '*' token 在最后一行。

很抱歉问了这么一个基本问题,但我错过了什么?

【问题讨论】:

  • cellNumber是什么变量? switch 语句来自 C,因此使用 Objective-C 类型可能会出错。
  • C 仅支持 switch/case 的类积分对象,如果这是这里的问题,我希望得到不同的错误消息。
  • Objective-C 是否遵循 C99(和 C++)并允许您在任何地方声明变量,还是只能在块的开头这样做?如果您被限制在块的开头声明它们,那么您可以通过在“case 1:”的“:”和匹配的“}”之后放置“{”来修复语法错误在案件结束之前。
  • 我不知道 Objective-C 是从 C89 分叉出来的,还是它也借用了 C99/C++ 结构。无论哪种方式,跳过 声明真的很可怕......
  • 您可以在 Xcode 中将 C89 或 C99(或 GNU99)设置为构建属性; Objective-C 位于您选择的 C 标准之上。

标签: objective-c switch-statement


【解决方案1】:

我手头没有合适的 Objective-C 编译器,但只要 C 结构相同:

switch { … } 为您提供 一个 块级范围,而不是每个 case 一个。在范围开头以外的任何地方声明变量都是非法的,并且在 switch 内是特别危险的,因为它的初始化可能会被跳过。

以下任一方法能否解决问题?

NSString *viewDataKey;
switch (cellNumber) {
    case 1:
        viewDataKey = @"Name";
    …
}

switch (cellNumber) {
    case 1: {
        NSString *viewDataKey = @"Name";
        …
    }
    …
}

【讨论】:

  • 写/Declaring a variable anywhere other than the beginning of the scope is illegal。这在 C99 中是不正确的。 C99 既允许这一点,也定义了“控制跳过声明”时发生的情况的语义以及在这种情况下该声明的值。
  • 我忘了指出哪个选项解决了问题,哎呀。我使用了第一个来解决问题 - 我不认为我测试了第二个建议,这太糟糕了,因为你们看起来好像在进行一场很好的讨论!
【解决方案2】:

您不能在 case 语句的开头声明变量。制作一个仅包含它的测试用例,你会得到同样的错误。

这与在块的中间声明的变量无关——即使采用允许不会使 GCC 接受在 case 语句开头的声明的标准。看来 GCC 将 case 标签视为该行的一部分,因此不允许在此处声明。

一个简单的解决方法是在 case 的开头放置一个分号,这样声明就不会放在开头。

【讨论】:

  • 错误。 switch (0) { int i; } 甚至可以在 C89 中完美编译。
  • 不是假的。我刚刚通过 GCC 从 Aragorn 的帖子中运行了你的示例并得到了同样的错误。
  • 我声称“不能在 case 语句中声明变量”是错误的。尝试在我之前的评论中给 GCC 一个小例子。
  • 哦,我明白了,您说的是case 标签,而不是switch。令人困惑的是谈论它的“开始”——case 只是一个标签,因此只能标注语句。这是一个有效的观点。
  • 这个答案的发布者是正确的。问题的根源在于 C99 BNF 语法,它(松散地)将标记语句定义为:...: statement。简而言之,没有办法从statementdeclarationcompound-statement(即{ ... })(松散地)将... 部分定义为zero or more block-items,块项目(松散地)定义为statement or declaration。此外,@Dan Olson 的评论既错误又不适用于 C99,它非常清楚地定义了混合声明和语句 wrt/初始化(C99 6.8.6.1 等)的语义。
【解决方案3】:

在 C 语言中,您只能在任何非声明语句之前在块的开头声明变量。

{
   /* you can declare variables here */

   /* block statements */

   /* You can't declare variables here */
}

在 C++ 中,您可以在任何需要的地方声明变量。

【讨论】:

  • switch (1) { case 0: int i = 1; break; default: /* wtf is i? */; } 即使您可以在任何地方声明变量,switch 内部也是危险
  • 使用 Visual Studio 2008 编译 c 文件。是 -> 错误 C2143:语法错误:缺少“;”在“类型”之前 =)
  • 在 C++ 中跳过初始化程序比在 C 中更危险,MSVC 更像是 C++ 编译器而不是 C 编译器。我并不惊讶它不喜欢这种垃圾。
  • 在 C 模式 (/TC) 中它会给出错误,而在 C++ 模式 (/TP) 中它编译没有错误。 =)
【解决方案4】:

您可以在 switch 语句中创建一个变量,但您必须在一个块中创建它,以便定义该变量的范围。

例子:

switch(number){

    case 1:
        {
            // Create object here
            // object is defined only for the scope of this block
        }
        break;
    case 2:
        {
            // etc.
        }
        break;
    default:
        break;

}

【讨论】:

  • 这是对一个非常古老的问题的新答案,并且已被接受。你的答案提供了其他人没有提供的什么?
  • 这是为了替代接受的答案中出现的第一个 switch 语句。在发布时,我没有注意到提供的第二个 switch 语句中与 case 语句内联的括号。
【解决方案5】:

在 switch 块中声明变量可能无效吗?

【讨论】:

  • 正如我在 Chuck 的回答中所说:switch (0) { int i; } 是有效的 C89,而 Objective-C 是 C 的真正超集(与 C++ 不同),因此 C 中的所有合法内容(模被盗标识符)在Objective-C。
【解决方案6】:

如何解决警告:

1.在案例块的第一行插入一个;

2.将代码放在大括号内

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-16
    • 1970-01-01
    • 2013-05-18
    • 2015-12-15
    • 1970-01-01
    • 2020-12-27
    相关资源
    最近更新 更多