Skipping switch cases via false loop is a valid operation?

北慕城南 提交于 2020-01-04 04:18:09

问题


Would this be legal code or breaking any rules?

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

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

    } while (0);    

    case 9:
        /*...*/

        break;

    default:
        break;
}

Would this be a legal way of executing case 6 followed by case 7 but only if some conditions are met? Or would this lead into undefined behavior and lets nasal dragons come out of the switch? p.s. my Question is refering to c99.

EDIT:

What i want to do is the following: assume, case 9, has to be executed in everycase. If expr is 6, i have to execute 6, under some conditions 7 and after that 9 or if expr is 7 its 7->9 so i just want to skip 7 if some conditions are met, but i cant change the order of 6,7,9.

EDIT2:

I'm not looking for an alternative soloution, I'm just interested in the behavior of this snippet.

If a switch statement has an associated case or default label within the scope of an identifier with a variably modified type, the entire switch statement shall be within the scope of that identifier.

from ISO/IEC 9899:TC3 6.8.4.2->3

Lets me feel unsure about its behavior. But I'm not sure that would aim code like mine snippet too.


回答1:


Whilst I believe the above code is valid, I would make it more explicit:

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;

}

Alternatively, which is the cleaner solution: move what the 6, 7 and 9 cases does into individual functions, and call the relevant functions (more than once, if needed) in the switch-statement, and have proper "break" after each case...




回答2:


Maybe I'm one of those lousy programmers. I'm not sure about the standards, but I've been doing things like that when it's needed. That said, if I wanted to do what you have stated in your question, I'd do something like this:

#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;
}

i.e. an if statement is more intrinsic here IMO.




回答3:


Valid yes; doing what you want? I doubt it.

Assuming the breaks you have put in are the only ones, then assuming the compiler doesn't get into a complete state (not implausible frankly, especially if you have optimisations turned up), then the following will happen

case 9:: runs its block and continues default: runs its block and continues case 7 : runs its block repeatedly forever case 6 : run's its block, maybe 7, repeats forever

To do what you want, remove the do..while, and put the if block at the end of the 6 around the 7, possibly putting a guard to check whether you are in the 6 or 7 case.

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

        break;

    default:
        break;
}

However, it's not how I'd do it. This is probably one where wrapping it into child functions would make sense:

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

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

is another way which is probably clearer.

and for completeness...

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


来源:https://stackoverflow.com/questions/18210824/skipping-switch-cases-via-false-loop-is-a-valid-operation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!