通过false循环跳过switch case是一种有效的操作?

时间:2013-08-13 13:44:31

标签: c c99 undefined-behavior

这是合法代码还是违反任何规则?

switch (expr)
{
    do
    {
        case 6:
            /*...*/

            if (/*...*/)
                break;
        case 7:
            /*...*/

    } while (0);    

    case 9:
        /*...*/

        break;

    default:
        break;
}

这是否是执行案例6的合法方式,然后是案例7,但只有在满足某些条件的情况下? 或者这会导致未定义的行为并让鼻龙从交换机中出来? 附:我的问题是参考c99。

编辑:

我想做的是以下内容: 假设案例9必须在每个案例中执行。如果expr是6,我必须执行6,在某些条件下7和之后9或如果expr是7则7-> 9 所以我只想在满足某些条件的情况下跳过7,但我无法改变6,7,9的顺序。

EDIT2:

我不是在寻找替代解决方案,我只是对这段代码的行为感兴趣。

  

如果switch语句在一个范围内有关联的case或default标签   具有可变修改类型的标识符,整个switch语句应在   该标识符的范围。

来自ISO / IEC 9899:TC3 6.8.4.2-> 3

让我对它的行为感到不确定。 但我不确定那会像我的片段一样瞄准代码。

3 个答案:

答案 0 :(得分:1)

虽然我相信上面的代码是有效的,但我会更明确地说明:

case 6:
   ... 

   /* fall through */
case 7:
   if (expr != 6 || condition_to_run_7)
   {
       do whatever 7 does;
   }
   if (should_not_do_9)

case 9:
   ... 
   break;

}

或者,这是更清洁的解决方案:将6,7和9个案例移动到单个函数中,并在switch语句中调用相关函数(如果需要,不止一次),并进行适当的“中断”在每个案件之后......

答案 1 :(得分:1)

也许我是那些糟糕的程序员之一。我不确定标准,但是在需要的时候我一直在做这样的事情。也就是说,如果我想做你在问题中所说的话,我会做这样的事情:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    int iCnt, iTmp;

    for(iCnt = 1; argc > iCnt; iCnt ++)
    {
        iTmp = (int) strtol(argv[iCnt], NULL, 10);

        switch(iTmp)
        {
            case 6:
                printf("Case 6\n");

            /* change this condition to whatever suits you */
            if (argc - 1 == iCnt)
            {
            case 7:
                printf("Case 7\n");
            }

            case 9:
                printf("Case 9\n");
            default:
                printf("Default case\n");
        }

        printf("\n");
    }

    return 0;
}

即。 if语句在IMO中更为内在。

答案 2 :(得分:0)

有效是;做你想要的?我对此表示怀疑。

假设您输入的break,那么假设编译器没有进入完整状态(坦率地说并非难以置信,特别是如果您已经优化了up),然后会发生以下情况

case 9::运行阻止并继续 default:运行阻止并继续 case 7:永远重复阻止它 case 6:运行它的块,也许是7,永远重复

要执行您想要的操作,请删除do..while,并将if块放在6周围7的末尾,可能会让警卫检查您是否在6或7个案例。

switch (expr)
{
    case 6:
        /*...*/       
            break;
    case 7:
      if ( expr==7 || !/*...*/)
      { 
        /*...*/
      }
    case 9:
        /*...*/

        break;

    default:
        break;
}

但是,我不是这样做的。这可能是将其包装到子函数中的意义:

void handle6() { /*...*/ }
void handle7() { /*...*/ }
void handle9() { /*...*/ }

switch (expr)
{
  case 6:
    handle6();
    if( /*...*/ ) handle7();
    handle9();
    break;
  case 7:
    handle7();
  case 9:
    handle9();
    break;
  default:
    /*...*/
}

是另一种可能更清晰的方式。

并且为了完整......

switch( expr )
{
    case 6:
        /*...*/
        if( /*...*/ ) goto case_9;
    case 7:
        /*...*/
    case 9:
case_9:
        /*...*/
        break;
    default:
        break;
}