Using an array of function pointer instead of switch - c

Is there any difference between using function pointer array and switch.
ı wrote a code like this
// Declaritons of add-substract-multiply funcitons
void (*fun_ptr_arr[])(int, int) = {add, subtract, multiply};
unsigned int ch, a = 15, b = 10;
printf("Enter Choice: 0 for add, 1 for subtract and 2 "
"for multiply\n");
scanf("%d", &ch);
if (ch > 2) return 0;
(*fun_ptr_arr[ch])(a, b);
and ı wonder what would be better here this code or using a switch ?
(in terms of performance btw)

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

Related

Difference between a lookup table and a jump table

I know that jump tables are mainly used to create switch statements in assembly:
int a = 5;
switch (a){
case 5:
...
break;
...
}
In this case, jump is just a pointer to a memory address which has instructions to do case 5 work.
If i'm not mistaking, a lookup table has pre calculated results in an array? so instead of writing code to calculate them you just return the array index? Sort of like a HashMap.
Above two sound very similar to me, are they basically the same thing? One points to instructions and the other returns pre calculated results?
If i'm not mistaking, a lookup table has pre calculated results in an array? so instead of writing code to calculate them you just return the array index? Sort of like a HashMap.
Correct. What's stored at that index could be data, or a pointer to data, or a pointer to a function etc etc.
A jump table is simply a look-up table where each index corresponds to a function, most commonly implemented in C as an array of function pointers.
Jump tables are, as you mention, native code that's arranged in a way that's easy to jump to depending on integer values. If the jump table is comprised of just short jump instructions, you can multiply your switch value by 3 and add the offset of the first entry in the table and jump (JMP or CALL) to it.
Lookup tables on the other hand are just raw data. It's still stored in a packed format so you can access it through a linear operation on your index (size * index + offset), but to make use of it you use an indirect move (MOV dest, [expression]) instead of physically jumping to it.
Keep in mind that lookup tables are just an optimization, albeit a huge one, you can load values into registers with a jump table as well. This is an is-a relationship.
What happens under the hood is up the compiler. But you're right on your observations. Here is a snippet demonstrating what compilers often do to switch statements:
#include <stdio.h>
void foo(void) { printf("foo\n"); }
void bar(void) { printf("bar\n"); }
int main(void)
{
// Array of size 2 of pointer to function without arguments returning void
// Yes, declaring function pointers is not intuitive...
void (*f[2])(void);
f[0] = foo;
f[1] = bar;
int x;
printf("Enter a number (0 or 1): ");
scanf("%d", &x);
printf("Using switch\n");
switch(x) {
case 0: foo(); break;
case 1: bar(); break;
}
printf("Using array of function pointers\n");
f[x]();
}

Replace switch/case by #ifdef or something similar

I'm trying to replace the switch/case structure by an other tool doing the same thing but with better performance ( less execution time ... ), I have in mind the #ifdef method but I have no idea how to use it in such situation:
float k_function(float *x,float *y,struct svm_model model)
{
int i;
float sum=0.0;
switch(model.model_kernel_type)
{
case LINEAR :
return result1;
case POLY :
return result2;
case RBF :
return result3;
case SIGMOID :
return result4;
default :
return 0;
}
}
PS :
typedef enum kernel_type {LINEAR, POLY, RBF, SIGMOID};
As I already commented, I do not believe preprocessor statements are what you are looking for. To use a preprocessor conditional, model.model_kernel_type would need to be a constant defined using a #define statement.
I do not know the internals of the switch statement, as it could be O(n) or O(1) depending on how the compiler handles it. If you needed to be sure of a O(1) time complexity, you could simply replace your switch statement with a lookup table like so:
float model_type_results[4] = {result1, result2, result3, result4};
...
return model_type_results[model.model_kernel_type];
I imagine the problem is not just 1 case statement, but code that is littered with similar case statements.
The c++ virtual function table is a similar concept for avoiding these sorts of case statements proliferating through the code. It is not actually difficult to implement function table semantics in C structures.
Traditionally, they have been written as just member function pointers, but the use of a single per-class function table pointer is more space efficient if there are many objects of each class.
#ifdef is a compile-time operation, not a run-time operation. It's not the solution you are looking for here.
Honestly, if your switch only contains four cases, there's not a lot you can do to improve on it. If you're seeing any kind of slowdown here, it's in how your results are being computed (which you don't show).

Place function instructions successively in program memory

Say I have a program which controls some Christmas lights (this isn't the actual application, only an example). These lights have a few different calculations to determine whether a light, i, will be lit in a given frame, t. Each of i and t is a uint8_t, so it can be assumed that there are 256 lights and t will loop each 256 frames. Some light patterns could be the following:
int flash(uint8_t t, uint8_t i) {
return t&1;}
int alternate(uint8_t t, uint8_t i) {
return i&1 == t&1;}
int loop(uint8_t t, uint8_t i) {
return i == t;}
If I then wanted to implement a mode-changing system that would loop through these modes, I could use a function pointer array int (*modes)(uint8_t, uint8_t)[3]. But, since these are all such short functions, is there any way I could instead force the compiler to place the functions directly after one another in program memory, sort of like an inline array?
The idea would be that to access one of these functions wouldn't require evaluating the pointer, and you could instead tell the processor the correct function is at modes + pitch*mode where pitch is the spacing between functions (at least the length of the longest).
I ask more out of curiosity than requirement, because I doubt this would actually cause much of a speed improvement.
What you are asking for is not directly available in C. But such logic can be possible in assembler, and C compilers might utilize different assembler tricks depending on CPU, optimization level etc. Try to just make the logic small and compact, mark the different functions as static, and use an switch() block in C and look at the assembler the compiler generates.
You could use a switch statement, like:
#define FLASH 1
#define ALTERNATE 2
#define LOOP 3
int patternexecute(uint8_t t, uint8_t i, int pattern)
{
switch (pattern) {
case FLASH: return t&1;
case ALTERNATE: return i&1 == t&1;
case LOOP: return i == t;
}
return 0;
}

Designing Around a Large Number of Discrete Functions in C

Greetings and salutations,
I am looking for information regrading design patterns for working with a large number of functions in C99.
Background:
I am working on a complete G-Code interpreter for my pet project, a desktop CNC mill. Currently, commands are sent over a serial interface to an AVR microcontroller. These commands are then parsed and executed to make the milling head move. a typical example of a line might look like
N01 F5.0 G90 M48 G1 X1 Y2 Z3
where G90, M48, and G1 are "action" codes and F5.0, X1, Y2, Z3 are parameters (N01 is the optional line number and is ignored). Currently the parsing is coming along swimmingly, but now it is time to make the machine actually move.
For each of the G and M codes, a specific action needs to be taken. This ranges from controlled motion to coolant activation/deactivation, to performing canned cycles. To this end, my current design features a function that uses a switch to select the proper function and return a pointer to that function which can then be used to call the individual code's function at the proper time.
Questions:
1) Is there a better way to resolve an arbitrary code to its respective function than a switch statement? Note that this is being implemented on a microcontroller and memory is EXTREMELY tight (2K total). I have considered a lookup table but, unfortunately, the code distribution is sparse leading to a lot of wasted space. There are ~100 distinct codes and sub-codes.
2) How does one go about function pointers in C when the names (and possibly signatures) may change? If the function signatures are different, is this even possible?
3) Assuming the functions have the same signature (which is where I am leaning), is there a way to typedef a generic type of that signature to be passed around and called from?
My apologies for the scattered questioning. Thank you in advance for your assistance.
1) Perfect hashing may be used to map the keywords to token numbers (opcodes) , which can be used to index a table of function pointers. The number of required arguments can also be put in this table.
2) You don's want overloaded / heterogeneous functions. Optional arguments might be possible.
3) your only choice is to use varargs, IMHO
I'm not an expert on embedded systems, but I have experience with VLSI. So sorry if I'm stating the obvious.
The function-pointer approach is probably the best way. But you'll need to either:
Arrange all your action codes to be consecutive in address.
Implement an action code decoder similar to an opcode decoder in a normal processor.
The first option is probably the better way (simple and small memory footprint). But if you can't control your action codes, you'll need to implement a decoder via another lookup table.
I'm not entirely sure on what you mean by "function signature". Function pointers should just be a number - which the compiler resolves.
EDIT:
Either way, I think two lookup tables (1 for function pointers, and one for decoder) is still going to be much smaller than a large switch statement. For varying parameters, use "dummy" parameters to make them all consistent. I'm not sure what the consequences of force casting everything to void-pointers to structs will be on an embedded processor.
EDIT 2:
Actually, a decoder can't be implementated with just a lookup table if the opcode space is too large. My mistake there. So 1 is really the only viable option.
Is there a better way ... than a switch statement?
Make a list of all valid action codes (a constant in program memory, so it doesn't use any of your scarce RAM), and sequentially compare each one with the received code. Perhaps reserve index "0" to mean "unknown action code".
For example:
// Warning: untested code.
typedef int (*ActionFunctionPointer)( int, int, char * );
struct parse_item{
const char action_letter;
const int action_number; // you might be able to get away with a single byte here, if none of your actions are above 255.
// alas, http://reprap.org/wiki/G-code mentions a "M501" code.
const ActionFunctionPointer action_function_pointer;
};
int m0_handler( int speed, int extrude_rate, char * message ){ // M0: Stop
speed_x = 0; speed_y = 0; speed_z = 0; speed_e = 0;
}
int g4_handler ( int dwell_time, int extrude_rate, char * message ){ // G4: Dwell
delay(dwell_time);
}
const struct parse_item parse_table[] = {
{ '\0', 0, unrecognized_action } // special error-handler
{ 'M', 0, m0_handler }, // M0: Stop
// ...
{ 'G', 4, g4_handler }, // G4: Dwell
{ '\0', 0, unrecognized_action } // special error-handler
}
ActionFunctionPointer get_action_function_pointer( char * buffer ){
char letter = get_letter( buffer );
int action_number = get_number( buffer );
int index = 0;
ActionFunctionPointer f = 0;
do{
index++;
if( (letter == parse_table[index].action_letter ) and
(action_number == parse_table[index].action_number) ){
f = parse_table[index].action_function_pointer;
};
if('\0' == parse_table[index].action_letter ){
index = 0;
f = unrecognized_action;
};
}while(0 == f);
return f;
}
How does one go about function pointers in C when the names (and
possibly signatures) may change? If the function signatures are
different, is this even possible?
It's possible to create a function pointer in C that (at different times) points to functions with more or less parameters (different signatures) using varargs.
Alternatively, you can force all the functions that might possibly be pointed to by that function pointer to all have exactly the same parameters and return value (the same signature) by adding "dummy" parameters to the functions that require fewer parameters than the others.
In my experience, the "dummy parameters" approach seems to be easier to understand and use less memory than the varargs approach.
Is there a way to typedef a generic type of that signature
to be passed around and called from?
Yes.
Pretty much all the code I've ever seen that uses function pointers
also creates a typedef to refer to that particular type of function.
(Except, of course, for Obfuscated contest entries).
See the above example and Wikibooks: C programming: pointers to functions for details.
p.s.:
Is there some reason you are re-inventing the wheel?
Could maybe perhaps one of the following pre-existing G-code interpreters for the AVR work for you, perhaps with a little tweaking?
FiveD,
Sprinter,
Marlin,
Teacup Firmware,
sjfw,
Makerbot,
or
Grbl?
(See http://reprap.org/wiki/Comparison_of_RepRap_Firmwares ).

what is the alternate way of doing function of switch-case (and if-else) in c?

what is the alternate way of doing function of switch-case (and if-else) in c?
Function pointers are one alternative. Consider the following snippet that calls a function through a function pointer array:
#include <stdio.h>
void fn0(int n) { printf ("fn0, n = %d\n",n); }
void fn1(int n) { printf ("fn1, n = %d\n",n); }
void fn2(int n) { printf ("fn2, n = %d\n",n); }
void fn3(int n) { printf ("fn3, n = %d\n",n); }
static void (*fn[])(int) = {fn0, fn1, fn2, fn3};
int main(void) {
int i;
for (i = 0; i < 4; i++)
fn[i](10-i);
return 0;
}
This generates:
fn0, n = 10
fn1, n = 9
fn2, n = 8
fn3, n = 7
This sort of construct makes it very easy to implement things such as finite state machines where, instead of a massive switch statement or near-unmanageable nested if's, you can just use an integer state variable to index into an array of function pointers.
You could always use gotos... :-p
Function pointers and a semi implementation of the strategy pattern :)
.. though youll need some logic to determine which function to call
There are several different ways to handle conditional branch-and-switch scenarios in C.
The typical patterns, which you yourself mention, are switch( ) statements and if/else if/else groups. However, sometimes these flow control constructs are not the best choice for certain problems. Specifically cases such as:
High performance branching over a large domain
Branching on value domains only known at runtime
Changing the branch paths at runtime based on other conditions
In these cases, there are two patterns that I find helpful:
The Strategy pattern with a direct dispatch
The Strategy pattern with a chained dispatch
In the first approach, you map each value from your domain to a collection of function pointers. Each function handles a particular case (value) from your domain. This allows you to "jump" directly to the right handler for a particular case. This pattern works well when each case is separated from all the others and there is little or no overlapping logic.
In the second approach, you chain all of the dispatch methods together - and call each of them for all cases. Each dispatched method decides if it handles the case or not, and either returns immediately or performs some processing. This pattern is useful when there is overlap between the responsibilities of some of the handlers. It is somewhat less performant, since multiple handlers are invoked, and each decides whether it needs to perform its processing. However, this is one of the easier ways to deal with overlapping logic - the kind you could normally handle in a switch() statement with fall through (or jump) conditions.
You should only use one of these techniques if the problem really requires it, since they are less obvious to future developers and can introduce unnecessary complexity and maintenance problems if implemented poorly. It also makes your code more difficult to understand, over more common constructs like switch or if/else.

Resources