Can you spot the problem with this code?
switch (day_of_week())
{
defualt : /*...*/ break;
case monday : /*...*/ break;
case tuesday: /*...*/ break;
...
}
It's not the fact that
the default is at the top. That's perfectly legal. The fault is
that default is spelled incorrectly. Yet it compiles without error.
What's going on? The answer is that the defualt: is being seen by
the compiler as a goto label! Does your compiler issue a warning for
this? A colour syntax highlighter would be a useful in this situation.
For the next error I can imagine Sherlock Holmes, crouched over a keyboard, debugging C code. Eventually he tracks the bug to a case without a break...
switch (day_of_week())
{
case monday : /*...*/
case tuesday: /*...*/ break;
...
default: /*...*/ break;
}
In this code, if expression is equal to monday then the flow of
control will pass to case monday:. However, since there is
no break with that case, the flow of control passes straight on
to case tuesday. That does have a break, so after tuesdays
code has finished, the flow of control finally passes to the end
of the switch statement. No doubt Dr.Watson would chronicle this
as "The case of the missing break". ;-} [1] [2]
Sometimes you want to create a variable for use just inside a switch. You could do this...
int sect;
/* 20 lines of code here */
switch (day_of_week())
{
...
}
...but following good practice you declare the variable in
its innermost scope, and write this...
switch (day_of_week())
{
int sect;
case monday:
...
}
The danger is that it's now a very short step to this...
switch (day_of_week())
{
int sect = beetle();
case monday:
...
}
The flow of control will never call beetle(),
so if the code assumes sect will be correctly initialized by beetle()
, then tough, because it won't be.
Finally you can't have two cases with the same constant.
switch (penny(lane))
{
case 0:
case 0:
}
This just won't compile. Strangely, this can be useful.
It's yet another way to implement a compile time assertion.
#define COMPILE_TIME_ASSERT(predicate) \
switch(0){case 0:case predicate:;}
Now if predicate evaluates to true (i.e., 1) then the
case labels will be 0 and 1. Different. Ok. If predicate
evaluates to false (i.e., 0) then the case labels will be 0 and 0. The same. Compile
time error.
#include <limits.h>
#define CHECK_BITSIZE(type, size) \
COMPILE_TIME_ASSERT(sizeof(type) * CHAR_BIT == size)
void check_int_bitsizes(void)
{
CHECK_BITSIZE(char, 8);
CHECK_BITSIZE(int, 16);
CHECK_BITSIZE(long, 32);
}
That's all for now.
Cheers
Jon Jagger
jon@jaggersoft.com