The trouble comes from insisting on using
switch. From attempts to forcefully squeeze an idea into an incompatible container. Just let go.
C’s
switch could easily support pointers. It’s trivial: express it in terms of
if-else and there is no problem for the compiler to follow this route. But in the process of changing semantics we’d lose what C’s
switch currently offers.
I find storing a register pointer and the bitmask in a descriptor the most elegant and clean way. Yet, this may be a poor choice for a microcontroller. I don’t know this microcontroller or your constraints. However it’s often the case that controllers have dedicated instructions for setting/clearning bits in registers. If that’s the case, after the right execution path is selected, the entire operation is stored and executed in a single instruction, and all its data loaded behind the scenes. With the descriptor solution this isn’t going to happen: data has to be stored separately, also constructed if kept in SRAM, the code needs to actively load it and process, with construction, loading, and setting taking many additional instructions. In a heavily constrained environment this may be too costly in therms of both space and time. But I agree this is the cleanest option.
If you wish to have matching working as you conceived in your original example, just replace it with series of
if-else. It would have to result in the same code anyway: comparing the pointer against each single option, in order, one by one. There is no loss.
(1)If you follow the port identifiers idea, consider this kind of a code:
enum UartPort {uart1, uart2, uart3, uart4};
static PortType* portById(enum UartPort port) {
switch (port) {
case uart1: return pointer1;
case uart2: return pointer2;
case uart3: return pointer3;
case uart4: return pointer4;
default: abort();
}
}
The advangage of this code is that, if
port is known at compile time, code generated by any decent compiler will behave as if
pointerN was used directly in code.
(2) That means: zero cost of invoking
portById.
(1) Hypothetically a compiler might make a more optimal implementation, if e.g. addresses representing pointers form a sequence. But not only I don’t know of a compiler doing this now, this kind of hypothetical may as well work the other way (for
if-else).
(2) If the one you use doesn’t, then regarding performance we have a much bigger problem than that.
