3

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.

dhein
  • 6,431
  • 4
  • 42
  • 74
  • 1
    Can you describe what you are actually trying to do? I believe it's valid code, but there may be some better solution, perhaps? – Mats Petersson Aug 13 '13 at 13:45
  • Duff's device mixes `do`/`while` and `switch` similarly. I'd wager your example does not include UB. – Brian Cain Aug 13 '13 at 13:49
  • @Mats Petersson done :) – dhein Aug 13 '13 at 13:50
  • @Brian Cainyeah, but Duff's device was like 10 years before c89, and was build for an realy special case. the method off duff's device is almost every compiler using afaik. So I'm not sure about there changed something up to c89 and c99, because this looking like kind of goto, whichs use has been alot restricted too. – dhein Aug 13 '13 at 13:53
  • I take it back, there's no label to address the `do`, so it would be ignored, right? – Brian Cain Aug 13 '13 at 13:54
  • it might be legal. it's breaking pretty much any rules there might be about the code being maintainable by someone else – Tom Tanner Aug 13 '13 at 15:06
  • 3
    Using `goto` would be a whole lot clearer. – sh1 Aug 13 '13 at 21:58
  • Slowly im getting anoyed... I did'nt ask for any hint of improoving this code. I didn't even say this is a good way. I just asked for the conformence refering to ISO/IEC 9899. So plz stop telling me I should use a goto a if-statement or anything else. I asked for the UB of a case should be in the whole scope. – dhein Aug 14 '13 at 08:49
  • Whether it breaks any rule or not depends on a project and a code-culture of the company. In all companies I've worked so far (12) it would break a couple of rules. Take a look at MISRA for having an impression of an industrially mature code. – Valentin H Jan 19 '14 at 10:09

3 Answers3

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...

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • the way of using functions would blow up my code increadible, because the switch has much more cases as in my snippet ;) – dhein Aug 13 '13 at 14:07
  • nope, because the conditions of which case has to get executed after which. is hardly nested. so i had to do for like 100 cases in each case like 20 if statements – dhein Aug 13 '13 at 14:09
  • 1
    So, it sounds like your switch-statement is really quite a mess... Maybe you should try refactoring the whole code. Using `do while` to combine cases like you suggest will be really hard to read, and atypical - it may be valid, but it really doesn't help people read the code - and if it's hard to read already because the switch is very big, making it harder to read doesn't seem like a good idea. – Mats Petersson Aug 13 '13 at 14:12
  • Well, but i didn't ask for any improvement, I just asked for the lagality of the code in reference to ISO/IEC 9899. So you didn't realy answer on my question, you did jsut suggest. – dhein Aug 14 '13 at 08:54
  • 1
    So, "Should I shoot myself in the foot with this shotgun, or use the pistol" should always be answered with "Pistol" or "Shot, because that's the only possible answer that answers the direct question? Even if the better answer is "Don't shoot yourself in the foot". What you are suggesting is making hard to read code harder to read, in other words, you are about to shoot yourself in the foot. I'm not the only one expressing the suggestion that "Maybe you should look at a different solution here". – Mats Petersson Aug 14 '13 at 09:02
1

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.

shinkou
  • 5,138
  • 1
  • 22
  • 32
  • Well, looks fine, but remember, I'm asking about this is lega code referign to the cstandard, especially of so posted rule. – dhein Aug 14 '13 at 05:32
0

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;
}
Oliver Matthews
  • 7,497
  • 3
  • 33
  • 36
  • the way of using functions would blow up my code increadible, because the switch has much more cases as in my snippet ;) – dhein Aug 13 '13 at 14:06
  • @Brian Cain If I'd use functions, in the way he describes in second snippet, I would have to do for example: `case 9: func1();->func4();->func7()->funcx();break;` and thats a lot of function calls just for every case. and the source file would als not get smaller – dhein Aug 13 '13 at 14:27
  • There's no limit on the count of function calls per case. It's great if we can make source files smaller, but if it comes at a cost of being able to comprehend the program then it's a Pyrrhic victory. The goal of the program is to communicate to a human what the computer should do. – Brian Cain Aug 13 '13 at 14:33
  • @Brian Cain Yes your right, and generally I also avoid such code, but as already said, its a question about the standard, and not about what would be the finest way. – dhein Aug 13 '13 at 14:53