|
Branch Tables via Function Pointer Arrays in C |
|
|
|
|
Written by Hemanshu Patel
|
|
Saturday, 24 November 2007 |
|
Page 6 of 6
Example 11pf [] is a static array of pointers to functions that take a const pointer to a const INT as an argument (i.e. the pointer nor what it points to may be modified) and return a const pointer to a volatile CHAR (i.e. the pointer may not be modified, but what it points to may change unexpectedly)
volatile CHAR * const fna(const INT *const i); //Example prototype
//Declaration using typedef typedef volatile CHAR * const (* const PFcPvC_cPcI)(const INT * const); static PVcPvC_cPcI[] = {fna,fnb,fnc, … fnz};
//Direct declaration static volatile CHAR * const (* const pf[])(const INT * const) = {fna, fnb, fnc, … fnz};
//Example use const INT a = 6; const INT * const aptr = &a; volatile CHAR * const res = pf[jump_index](aptr); //Method 1 volatile CHAR * const res = (*pf[jump_index])(aptr); //Method 2
while (*res) ; //Wait for volatile register to clear
With memory space qualifiers, things can get even more hairy. For most vendors, the memory space qualifier is treated syntactically as a type qualifier (such as const or volatile) and thus follows the same placement rules. For consistency, I place type qualifiers to the left of the "thing" being qualified. Where there are multiple type qualifiers, alphabetic ordering is used. Since memory space qualifiers are typically compiler extensions, they are normally preceded by an underscore, and hence come first alphabetically. Thus, a nasty declaration may look like this:
_ram const volatile UCHAR status_register;
To demonstrate memory space qualifier use, here is example 11 again, except this time memory space qualifiers have been added. The qualifiers are named _m1 … _m5.
Example 12pf [] is a static array of pointers to functions that take a const pointer to a const INT as an argument (i.e. the pointer nor what it points to may be modified) and return a const pointer to a volatile CHAR (i.e. the pointer may be modified, but what it points to may change unexpectedly). Each element of the declaration lies in a different memory space. In this particular case, it is assumed that you can even declare the memory space in which parameters passed by value appear. This is extreme, but is justified on pedagogical grounds.
/*An example prototype. This declaration reads as follows. Function fna is passed a const pointer in _m5 space that points to a const integer in _m4 space. It returns a const pointer in _m2 space to a volatile character in _m1 space. */
_m1 volatile CHAR * _m2 const fna(_m4 const INT * _m5 const i);
/*Declaration using typedef. This declaration reads as follows. PFcPvC_cPcI is a pointer to function data type, variables based upon which lie in _m3 space. Each Function is passed a const pointer in _m5 space that points to a const integer in _m4 space. It returns a const pointer in _m2 space to a volatile character in _m1 space. */
typedef _m1 volatile CHAR * _m2 const (* _m3 const PFcPvC_cPcI) (_m4 const INT * _m5 const); static PVcPvC_cPcI[] = {fna,fnb,fnc, … fnz};
/*Direct declaration. This declaration reads as follows. pf[] is a statically allocated constant array in _m3 space of pointers to functions. Each Function is passed a const pointer in _m5 space that points to a const integer in _m4 space. It returns a const pointer in _m2 space to a volatile character in _m1 space. */
static _m1 volatile CHAR * _m2 const (* _m3 const pf[]) (_m4 const INT * _m5 const) = {fna, fnb, fnc, … fnz};
//Declare a const variable that lies in _m4 space _m4 const INT a = 6;
//Now declare a const pointer in _m5 space that points to a const //variable that is in _m4 space _m4 const INT * _m5 const aptr = &a;
//Make the function call, and get back the pointer volatile CHAR * const res = pf[jump_index](&a); //Method 1 volatile CHAR * const res = (*pf[jump_index])(&a); //Method 2 while (*res) ; //Wait for volatile register to clear
|