Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a useful case using a switch statement without braces?

In H&S5 I encountered the "most bizarre" switch statement (8.7.1, p. 277) not using braces.
Here's the sample:

switch (x)
    default:
    if (prime(x))
        case 2: case 3: case 5: case 7:
            process_prime(x);
    else
        case 4: case 6: case 8: case 9: case 10:
            process_composite(x);

The idea seems to be to avoid the overhead of prime(x) for the most common small numbers.

When I saw that statement, I was confused about the missing braces, but checking the official grammar (C1X pre-standard, 6.8.4, p. 147), the syntax was correct: A switch statement just has a statement after the switch expression and the closing parenthesis.

But in my programming practice I never again encountered such a curious switch statement (and I wouldn't want to see any in code that I have to take responsibility for), but I started wondering:

Would any of you know such a switch expression, one without using braces, but still having meaning? Not just switch (i); (which is legal, but a NOP), but using at least two case labels having some sort of useful purpose?

like image 821
Johan Bezem Avatar asked Nov 14 '11 06:11

Johan Bezem


People also ask

Do you need braces in switch case?

The braces are always needed following the switch statement. No braces are needed following any case. If the variable is equal to one of the values following a case, then the code following the case is executed.

Do switch cases need curly braces?

Bookmark this question. Show activity on this post. In a C switch-case flow control, it's required to put curly braces { } after a case if variables are being defined in that block.

Is it possible to use a switch case statement without a default?

A switch statement can have an optional default case, which must appear at the end of the switch. The default case can be used for performing a task when none of the cases is true. No break is needed in the default case.

What case should be always be included in a switch statement?

Switch cases should almost always have a default case. 2. To handle 'default' actions, where the cases are for special behavior. You see this a LOT in menu-driven programs and bash shell scripts.


2 Answers

If you use control structures in macros a switch instead of if comes handy since it has no dangling else problem.

#define DEBUG_PRINT(...) switch (!debug_mode) case 0: fprintf(__VA_ARGS__)

With that you don't have surprises if a user of that macro puts this in an additional condition

if (unclear) DEBUG_PRINT(stderr, "This is really %unclear\n", unclear);
else {
 // do something reasonable here
}

Such a debug macro has the advantage of being always compiled (and then eventually optimized out). So the debug code has to remain valid through all the live time of the program.

Also observe here that it is important that the switch doesn't use {}, otherwise the if/else example wouldn't work either. All this could be achieved by other means (if/else , (void)0 and do/while tricks) but this one is the most convenient I know of.

And don't take me wrong, I don't say that everybody should use control structures inside macros, you certainly should know what you are doing. But there are situations where it is justified.

like image 103
Jens Gustedt Avatar answered Oct 23 '22 15:10

Jens Gustedt


Here's an example written by Dennis Ritchie in 1972 during his work on the first C compiler. The c02.c module, linked at the foot of page I just linked to, includes

easystmt()
{
    extern peeksym, peekc, cval;

    if((peeksym=symbol())==20)  /* name */
        return(peekc!=':');  /* not label */
    if (peeksym==19) {      /* keyword */
        switch(cval)
        case 10:    /* goto */
        case 11:    /* return */
        case 17:    /* break */
        case 18:    /* continue */
            return(1);
        return(0);
    }
    return(peeksym!=2);     /* { */
}

From reading his 1972 code it's clear Dennis was a fan of switch statements - he used them quite a bit. It's not so surprising given that almost everything was encoded as an int partly for lack of other data type possibilities. His compiler implementation used no structs at that stage because he was just in the middle of adding them to the language. Dynamic dispatch, vtables and polymorphism were a long way off. I've tried and failed to find a reference for this but if I recall correctly Dennis "invented" switch statements or at least contributed ideas leading to the form they take in C and considered them one of his best or proudest additions to the language.

The ability to leave out the braces makes switch statements formally similar to if, for, do and while statements, helping to simplify and unify the grammar. See the selection-statement and iteration-statement productions in the C grammar (e.g. in Appendix A13 of Kernighan and Ritchie, pages 236-237 in my copy) where these things are defined.

Obviously one can always add braces but maybe that seems heavy for such simple examples as this one. This example could be coded as a disjunctive if statement but I think one of the ideas Dennis had for switch was that the compiler is more clearly being offered the opportunity to optimise the implementation of the branching logic based on the particular constants involved.

like image 2
egyik Avatar answered Oct 23 '22 16:10

egyik