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?
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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With