Discrete Values - enum
¶
Discrete Values¶
Many times an integer’s value does not take the full possible range ⟶ Discrete values
Command identifiers (e.g. Unix
ioctl
’s)Possible baud rates on a UART
A state machine’s state
Discrete Values - Traditional Approach (1)¶
#define IDLE 0
#define WRITING_REQUEST 1
#define READING_RESPONSE 2
#define WAIT_RETRY 3
struct protocol_engine
{
int state;
...
};
|
Traditional approach
Drawback
|
Discrete Values - Traditional Approach (2)¶
switch (engine->state) {
case IDLE: ...;
case WRITING_REQUEST: ...;
case READING_RESPONSE: ...;
case WAIT_RETRY: ...;
default:
error("bad state");
break;
}
|
Questions
|
Discrete Values - Wishlist¶
Wishlist:
The value of a state is pointless. I don’t want to think about it. I.e.,
WRITING_REQUEST == 1
for no reason.Separate type for a state, for
Readability
Type safety (to prevent mixing with e.g. integers)
Compiler support in
switch
like, “forgot to addcase
label for newly introduced state”.⟶ Fully met in C++, only partly met (“Type safety”) in C
Discrete Values - enum
¶
enum state
{
IDLE,
WRITING_REQUEST,
READING_RESPONSE,
WAIT_RETRY
};
struct protocol_engine
{
enum state state;
...
};
|
Advantage:
But:
enum state s = 42;
|
Discrete Values - enum
and switch
¶
Wishlist item #3: “forgot to add case
label for newly
introduced state”
Adding New State enum state
{
IDLE,
WRITING_REQUEST,
READING_RESPONSE,
WAIT_RETRY,
/* Error handling */
PROTOCOL_ERROR
};
|
|
Discrete Values - enum
and switch
¶
switch (engine->state) {
case IDLE: ...;
case WRITING_REQUEST: ...;
case READING_RESPONSE: ...;
case WAIT_RETRY: ...;
default:
error("bad state");
break;
}
|
“
|
Discrete Values - Close to Perfection¶
switch (engine->state) {
case IDLE: ...;
case WRITING_REQUEST: ...;
case READING_RESPONSE: ...;
case WAIT_RETRY: ...;
/* no default here! */
}
|
|
$ gcc -Wswitch-enum ...
warning: enumeration value ‘PROTOCOL_ERROR’ not handled ...
$ gcc -Werror -Wswitch-enum ...
error: enumeration value ‘PROTOCOL_ERROR’ not handled ...