【问题标题】:Declaring variables inside C switch/case在 C switch/case 中声明变量
【发布时间】:2010-11-25 14:34:44
【问题描述】:

好吧,这实际上不是一个问题..

我只是偶尔发现有一种有趣的方法可以在 switch/case 块中声明局部变量。你可以这样写,而不是在每个 case 块中使用大括号:

switch (action) {
  int res;
  int value;
case ACTION_OPEN:
  res = open(...);
  ...
  break;
case  ...
}

所以,我只是想知道除了 gcc 之外还有哪些 C/C++ 编译器支持这种构造?它看起来像一个常见的跌倒。欢迎任何有关此结构的 cmets!

【问题讨论】:

  • +1,只是为了确定这是合法的 C++ 还是编译器的意外。如果允许的话可能会有用。
  • 一种更简单的方法是停止使用已经过时 11 年以上的 C 编译器。
  • 不过,除了偶尔的失败之外,我仍然更喜欢每个 case 块中的大括号,以实现更多的本地范围。这是一个品味问题。
  • 我将标签更改为 C,因为问题指定了 C,并且构造在 C++ 中完全完全不相关。
  • @DeadMG 为什么它在 C++ 中比在 C 中“完全和完全不相关”?标签是由原始海报设置的,所以我怀疑删除它是一件好事。 C++ 对此有附加规则(resvalue 不能被初始化并且不能是非 POD)。

标签: c++ c variables local switch-statement


【解决方案1】:

开关体只是一个普通的语句(在你的例子中是一个复合语句,看起来像{ ... }),它可以包含任何废话。包括案例标签。

Duffs device 滥用了这种开关原理。

很多人没有意识到即使像switch(0) ; 这样的东西也是一个有效的语句(而不是一个复合语句,它有一个空语句作为主体),虽然很没用。

【讨论】:

  • 这与变量声明无关。 Duff 没有在他的 switch 语句中声明变量,因为他那个时代的 C 编译器需要额外的块(可能会被翻译成 push/pop 指令)。
  • @larsmans Duff 的设备与变量声明无关,但与滥用 C 和 C++ 使用的 switch 结构有关。特别是,案例标签并不是真正的“特殊”,而只是跳转标签。一旦知道这一点,您就可以在 switch 正文中将声明语句放在 case 标签之前。
【解决方案2】:

任何符合标准的 C 或 C++ 编译器都允许这样做。即使是老式的(ISO C99 之前的)C 编译器也会允许这样做,但这只是因为变量声明位于块/复合语句的开头(由 {} 表示)。

请注意,switch 后面的内容几乎是一个正常的语句,除了大小写标签的可能性:

int main(int argc, char* argv[])
{
    switch (argc)
      default:
        puts("Hello, world!");

    return 0;
}

所以在 ANSI C89 中,大括号在这里发挥了魔力。

【讨论】:

    【解决方案3】:

    严格来说,您使用int 提出的案例在所有三种语言中都允许使用,但原因不同。

    C 允许在所有情况下(对于 C89)和除一个(对于 C99)之外的所有情况下跳过任何局部变量(算术、structunion、数组...)的定义。 C99 的例外是可变长度数组。

    C++ 仅允许对没有构造函数或析构函数的数据类型(通常称为 POD)进行此操作。

    因此,如果您在 C89 中的示例中使用类型 T 而不是 int,这始终有效,而在 C99 和 C++ 中,这取决于类型 T 是否正确。

    无论如何,所有这些都容易导致未初始化的变量,所以如果可以避免的话最好不要这样做。

    【讨论】:

      【解决方案4】:

      我认为 C99 允许(几乎)在块内的任何位置声明变量,因此这种行为应该被认为是合法的。我没有看到任何实际风险,因为它只是一个声明。

      【讨论】:

        猜你喜欢
        • 2021-12-05
        • 1970-01-01
        • 2020-12-27
        • 2021-12-13
        • 1970-01-01
        • 2015-08-02
        • 1970-01-01
        • 2013-05-15
        • 2017-02-03
        相关资源
        最近更新 更多