Bizarre switch statement in C
It’s been in my “Bizarre C” box for many years. Things you may want or need to know about, but never would want to duplicate.
Currently, I am researching for a new publication, maybe a PDF document, maybe a course, on the nooks an crannies of the C programming language. And I’m finding some abstruse samples, I can tell you.
But one example I found most bizarre at the time (around 1990), and which still is among my favorites to flabbergast experienced C programmers, I found in the best C programming reference I’ve known to date: “C – A Reference Manual” by Samuel P. Harbison and Guy L. Steele (see also the book’s website).
Imagine a calculation depending on certain numbers being prime or not. If the routine gets a prime parameter it executes one routine, if the parameter is not prime, another. Like this:
if (is_prime(a))
··process_prime(a);
else
··process_nonprime(a);
The if-statement is just that, a statement, a composite statement.
A switch-statement is composed of a switch keyword, the value on which to operate, and a, possibly composite, statement. It could be our if-statement, if we so choose. However, without any case/default-labels, the switch-statement would just jump over the statement so specified, effectively doing nothing. To remedy that, we put the default-label before the if-statement:
switch (a)
··default:
····if (is_prime(a))
······process_prime(a);
····else
······process_nonprime(a);
This code already looks strange, but it is functionally equivalent to the if-statement by itself.
If we now imagine the function is_prime(a) to be very expensive, it would make sense to take a shortcut around that function wherever possible. And if 99% of the values the variable a can have lie between 2 and 10 inclusive, it definitely would make sense to circumvent the is_prime() function, since we know the primeness of those values without calculation:
switch (a)
··default:
····if (is_prime(a))
··case 2: case 3: case 5: case 7:
······process_prime(a);
····else
··case 4: case 6: case 8: case 9: case 10:
······process_nonprime(a);
To understand why this is correct C, we need to realize that case-labels belonging to a switch-statement can be positioned anywhere within the boundaries of the composite statement belonging to the switch. In our case, this means until the semicolon after the process_nonprime(a) statement.
It works as follows:
- If
ais 3 upon execution of theswitch, the labelcase 3:is where execution continues after determining the value ofato be three, jumping into the middle of theif-statement and calling the functionprocess_primewith a parameter 3. After execution of that function, theif-statement is terminated, terminating the enclosingswitch-statement at the same time. - If
ais 8 upon execution of theswitch, the labelcase 8:is where execution continues after determining the value ofato be eight, jumping into the middle of theif-statement and calling the functionprocess_nonprimewith a parameter 8. After execution of that function, theif-statement is terminated, terminating the enclosingswitch-statement at the same time. - If
ais 29 upon execution of theswitch, the labeldefault:is where execution continues after determining that no known value is to be processed, executing theif-statement from its beginning. Depending on the value ofa(29 in this case) theif-condition determines which of the two alternative functions to call, just like a normalif-statement.
I can only agree with Sam Harbison and Guy Steele: “This is frankly the most bizarre switch statement we have ever seen that still has pretenses to being purposeful.”
Would you want the nuclear reactor around the corner being coded like this?
Happy coding!
Johan
Deutsch
English
Nederlands
