在if ... else语句中嵌入案例标签

时间:2014-04-01 00:30:09

标签: c++

G ++接受此代码,它的行为与我期望的一样:

#include <cassert>

void example (int value, bool condition) {

  switch (value) {
  case 0:
    if (condition) {
  case 1:
      assert(condition || value == 1);
    } else {
      assert(!condition && value == 0);
    }
    assert(value == 0 || value == 1);
  }

}

int main () {
  example(0, false);
  example(1, false);
  example(0, true);
  example(1, true);
}

也许这是一个愚蠢的基本问题但是,代码嗅到一边,将case标签放在if...else块中是否有效C ++,并且所有性能良好的编译器都会正确生成代码通过else输入时,跳过case 1块?

2 个答案:

答案 0 :(得分:6)

就C ++而言(草案N3936):

  • 案例和默认标签本身不会改变控制流程,在这些标签上继续畅通无阻
  • 通常,作为开关主题的子语句是复合和大小写,并且默认标签出现在(复合)子语句中包含的顶级语句,但这不是必需的。( §6.4.2 - 6)
  • 可以转换为块,但不能绕过初始化声明。 (§6.7 - 3)

你在做什么在技术上是可以的,当然这并不意味着你应该这样做。

答案 1 :(得分:4)

您所做的是完全标准的C ++代码,尽管我认为它不是特别容易阅读或维护。如果我们查看draft C++ standard部分6.4 选择语句,则switch语句的语法如下:

switch ( condition ) statement

语句包括标签,if,while,for etc ...和section 6.4.2 switch语句没有任何限制可以排除你正在显示的代码。

案例标签就像 goto 所使用的标签一样,6.1 标签声明部分对此进行了介绍,但它们仅限于在 switch语句

  

案例标签和默认标签只能在switch语句中出现。

6.7部分说我们可以转移到一个块,给出一些限制,例如不绕过声明初始化声明:

  

可以转换为块,但不能以初始化绕过声明的方式。从具有自动存储持续时间的变量不在范围内的点跳到 87 的程序是不正确的,除非该变量具有标量类型,类型具有普通性默认构造函数和一个普通的析构函数,这些类型之一的cv限定版本,或者前面类型之一的数组,并且在没有初始值设定项的情况下声明(8.5)。

脚注87说:

  

从switch语句的条件转移到case标签被认为是这方面的一个跳跃。

对于switch语句,最着名和最奇怪的用法之一可能是Duff's device,它有一个嵌入式while循环:

void send( int *to, const int *from, int  count)
{
        int n = (count + 7) / 8;
        switch(count % 8) 
        {
            case 0: do {    *to = *from++;   // <- Scope start
            case 7:         *to = *from++;
            case 6:         *to = *from++;
            case 5:         *to = *from++;
            case 4:         *to = *from++;
            case 3:         *to = *from++;
            case 2:         *to = *from++;
            case 1:         *to = *from++;
                        } while(--n > 0);    // <- Scope end
        }
}
相关问题