A switch
statement with adjacent numbers are often optimized to a function pointer look-up table internally.
Historically, compilers were bad at this and function pointer tables were always faster back in the days. Nowadays performance shouldn't be an argument for either version. In fact, one drawback with a manual function pointer table is that the compiler won't be able to inline the functions, something it can otherwise do when optimizing a switch
.
So you shouldn't use the function pointer version because it is faster/slower, but rather because it can improve readability and maintenance of the code.
It is for example common practice to use such function pointer tables when implementing finite state machines. Complex switch
statements on the other hand, are hard to read and there's various quirks with the syntax, such as the missing break
bug etc.
Finally, you can improve the readability of your code if you write like this instead:
typedef void operation_t (int op1, int op2); // function type
operation_t* const op_array[] = {add, subtract, multiply}; // read-only function pointer table
op_array[i](a, b); // call specific function