【问题标题】:Switch Without Case开关无外壳
【发布时间】:2013-08-08 18:46:36
【问题描述】:

今天,我无意中发现,在没有大小写的 switch 语句中编写代码时,我的编译器不会报错。 (它确实抱怨缺少 case 语句,但是在代码后面添加一个之后,并没有警告让我知道代码没用。)

我试图弄清楚是否有允许以下代码的目的,或者它是否只是“限制它的工作量更大,所以允许它”的那些事情之一。

#include <iostream>
void foo() {
   std::cout << "foo" << std::endl;
}

int main()
{
   for (int a = -10; a < 10; ++a)
   {
      switch(a)
      {
         foo();
      case 4:
         std::cout << "4" << std::endl;
      }
   }
}

现在当 a == 4 时,它会按预期输出“4”,并且它永远不会输出 foo。所以问题是,是否有一些(可能深奥但有用的)理由允许在第一个案例之前使用声明 foo();?我确定我不能在那里声明和初始化变量。

(FWIW,我已经在几个编译器上对此进行了测试,它们都产生了相同的行为。令人惊讶的是,它们也都没有输出警告。)

【问题讨论】:

  • 这是什么编译器?
  • 我已经在 MSVC 2012 和 GCC 4.8.1 上测试过了。
  • 嗯,很有趣。想到的一个想法是不必编写默认值:而只需在最后一种情况下编写代码。但是,这尖叫着潜在的不良做法:)
  • 你试过在 GCC 中使用-Wall 吗?
  • 好吧,我试过-Wall。在 GCC 的古董版本(AIX 上的 3.3.2)上,我收到了无法访问的代码警告。在较新的版本(Cygwin 上的 4.5.3)上,我没有收到任何警告。

标签: c++ switch-statement language-design


【解决方案1】:

是的,行为与语言中的设计一致,您可以在不同的地方添加代码。 Switch 语句比外观复杂得多,而且它们允许编写相当深奥的代码,不管它是否有意义。

如果你想花点时间看看switch的一些奇怪用法和case的位置,你可以看看boost asio库中协程的实现。您可以使用宏编写一个小函数,编译并查看生成的代码(宏扩展后)的样子。

【讨论】:

  • boost 的实现通常让我害怕,但现在你已经激起了我的好奇心。
  • @Shirik switch-sorcery 的典型例子是Duff's device:一个与do-while交织在一起的开关。
  • 忍者。我很高兴有人提到达夫的设备。我(很少)在嵌入式系统上使用这种魔法来分解长函数并使它们更容易重新启动。但是,如果您在使用 'goto' 时感觉很脏,那么在将开关用于此类入口点之前,您可能应该多考虑一下。
  • 不回答 de OP 问题,也不具体。
【解决方案2】:

来自MSDN:-

声明可以出现在复合语句的开头 开关体,但声明中包含的初始化是 不执行。 switch 语句直接将控制权转移到 正文中的可执行语句,绕过包含的行 初始化。

【讨论】:

  • 我不会将 MSDN 称为 the source,如果有什么标准是 THE 来源的话。
  • 是的,我确实看过 C++ 标准,但没有走得太远。我所做的只是向自己证明似乎没有任何限制它。这更像是“由于缺乏规则而允许”的事情之一。
  • @MadScienceDreams:这是非法的,因为 x 的初始化被 case 语句绕过了。
  • @Shirik 啊,看错了,还是没明白允许这段代码的意义。
猜你喜欢
  • 1970-01-01
  • 2017-04-21
  • 2010-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多