I would answer with a question: why are you using a switch statement and not if...else if?
Surprisingly, many programmers never ask that question but regard switch
for something fundamental that must be there in the language. That is not true! You can write any kind of C program without ever using switch
. Strictly speaking, switch
is a redundant feature.
So why use it?
Readability is not the reason why. switch
actually has far worse and less intuitive syntax than if-else. The need for break statements inside the switch, the weird syntax rules of switch that allows a case to be declared inside a local scope of another case, the arbitrary location of the default.
switch
is not only less readable, it is also much more bug-prone than if-else. The forgotten break is the most obvious hazard, that has lead to millions upon millions of hard-to-find bugs in software.
Another more obvious argument against switch
being more readable is this "bare bone" code:
if (A)
{
}
else if (B)
{
}
else if (C)
{
}
else
{
}
switch(something)
{
case A:
{
break;
}
case B:
{
break;
}
case C:
{
break;
}
default:
{
break;
}
}
The if and the switch above are equivalent in syntax and function, and should be compiled down to the very same machine code. Here is the statistics from this example
if-else switch
Symbols 33 65 // Not counting the expressions
Lines 12 19 // Not counting empty lines
switch requires more code for the same result, thus is must be regarded as less readable than if-else.
Before you start to argue about switch looking more like a table than if-else, that is all about code formatting, and irrelevant. Nothing in the standard prevents you from writing code like this:
if (A) {}
else if (B) {}
else if (C) {}
else {}
switch(something)
{
case A: { break; }
case B: { break; }
case C: { break; }
default: { break; }
}
I would consider either form to be readable, if you wish for some sort of minimal table-like syntax.
There may of course be aesthetic, superstitious or religious reasons why switch
should be used for readability, but I rather leave such off-topic discussions to non-programming related sites.
So switch is less safe and less readable than if-else. What then remains that may appeal to a programmer is efficiency. A programmer with n cases that must be tested by the program would surely like to have something that makes the search for the correct case as quick as possible. It is a bad idea to examine all cases in a linear fashion.
As you may know, it is possible to optimize an if-else or switch quite a lot, by implementing it as an array of function pointers:
typedef void (*Func_t)(void);
const Func_t cases [N] = { ... };
cases[i]();
This drastic optimization is often exactly what a compiler does when encountering a switch statement. However, this optimization can only be done if all cases are adjacent integers. If they are not adjacent, then the adjacency can be created through a const lookup table.
But if the cases aren't of integer type, the above optimization cannot be done. If they were floats, strings or something else, there is no sensible way to optimize the code.
So at least in my book, switch
only exists for this very purpose: it makes it easier for the compiler to create more effective code than if-else. Thus it falls into the same category as keywords inline, register etc, that also make it easier for the compiler to optimize your code.