|
Branch Tables via Function Pointer Arrays in C |
|
|
|
|
Written by Hemanshu Patel
|
|
Saturday, 24 November 2007 |
|
Page 3 of 6
Keypads The most often cited example for uses of function pointers is with keypads. The general idea is obvious. A keypad is normally arranged to produce a unique keycode. Based on the value of the key pressed, some action is taken. This can be handled via a switch statement. However, an array of function pointers is far more elegant. This is particularly true when the application has multiple user screens, with some key definitions changing from screen to screen (i.e., the system uses soft keys). In this case, a two dimensional array of function pointers is often used.
#define N_SCREENS 16 #define N_KEYS 6 /* Function prototypes for functions that appear in the jump table */ INT fnUp(void); INT fnDown(void); … INT fnMenu(void); INT fnNull(void);
INT keypress(uint8_t key, uint8_t screen) { static INT (* const pf[N_SCREENS][N_KEYS])(void) = { {fnUp, fnDown, fnNull, …, fnMenu}, {fnMenu, fnNull, …, fnHome}, … {fnF0, fnF1, …, fnF5} };
assert (key < N_KEYS); assert( screen < N_SCREENS); return (*pf[screen][key])(); //Call the function and return result }
INT fnNull(void) { /* Dummy function - used as an array filler */ return 0; }
There are several points to note about the above example:
* All functions to be named in a jump table should be prototyped. Prototyping is the best line of defense against including a function that expects the wrong parameters, or returns the wrong type. * As for earlier examples, the function table is declared within the function that makes use of it (and, thus, static). * The array is made const signifying that we wish it to remain unchanged. * The indices into the array are unsigned, such that only single sided bounds checking need be done. * In this case, I have chosen to use the assert() macro to provide the bounds checking. This is a good compromise between debugging ease and runtime efficiency. * A dummy function fnNull() has been declared. This is used where a keypress is undefined. Rather than explicitly testing to see whether a key is valid, the dummy function is invoked. This is usually the most efficient method of handling an function array that is only partially populated. * The functions that are called need not be unique. For example, a function such as fnMenu may appear many times in the same jump table.
|