First off, only concern yourself about the overhead if the overhead is
relevant - not all code has to be at top efficiency. But all code
benefits from being written in a clear and maintainable manner, with
minimal risk of errors. So keep that in mind when making such design
decisions.
I personally would not use function pointers here. You can have
different balances and opinions, and the rest of your code can influence
things, but I will list my justifications here.
1. You can get function pointers wrong. You can, of course, get all
kinds of things wrong - but when a function pointer goes wrong, it can
be extremely difficult to figure out what is happening and debug the code.
2. Switches have range-checking built in, array lookups here do not.
3. Switches can work directly with enumerated types which are almost
certainly a much better choice here for the type of "ops.export". Drop
the "magic numbers" and use names from an enumerated type. This makes
the switch clearer, and easier to maintain. It lets you use
"-Wswitch-enums" in gcc/clang to warn if the switch does not handle all
the cases.
4. Your ordering in the switch can be whatever suits your preferences
and for maintenance, not the numerical ordering needed for array
initialisation.
5. Now that you have an order free from numbers, there are no
complications or risks if you want to remove one of the actions.
6. The actions are run from within the switch, not via pointers. That
means the compiler can optimise far better, and - often more importantly
- can do more static analysis to find potential problems at compile
time. It also means you don't have to squeeze everything into one set
of parameters - different actions can have different parameters.
7. Tools that deal with call tracing work much better with the switch
version. That includes tools to check stack depth (rarely important on
PC's, but useful in small embedded systems), code coverage,
documentation, etc., can do a better job. If you are debugging and need
to work backwards to find how you got to a particular point in the
program, it is vastly easier if there are no function pointers in the way.
There are certainly situations where function pointers make code better
- in particular, using callbacks avoids dependencies between different
parts of the code. But for my own use, I rarely find them the best choice.