Function pointers - Simple use without confusion in C Programming

Pointer is one of the most used feature of C - Programming language. It gives us a lot of power to access and control. Function pointers are nothing but a pointer to a function. While learning the concept, it may seem a redundant feature to assign address of a function to a pointer and call the same function using the pointer. However, in simple programs, it is of no use. But, it make sense and it is the only way to achieve certain functionality using C-Programming language.

Good way to define function pointer

In an embedded project with different programs, pointer is of great use. For example, in an embedded project, one may want to do a soft reset. Which means nothing but jumping back to the starting address(most of the cases, the reset vector = address 0). In C program, this can be achieved by using a pointer, assign it to value 0 and call.
void (*pSoftReset)(void); /* Define a function pointer */
pSoftReset = (void (*)(void))0; /* Assign address 0 to pointer */
pSoftReset(); /* Function call using pointer */
In the above snippet, in line 1, a function pointer is defined. In line 2, pointer is initialized with address. Note the typecasting. 0 integer is typecast-ed to a function pointer with address value 0. Then, the function is called. It will never return as the initialization routines will initialize all the variables, stack etc. The same code can also be written in single line as
((void (*)(void))0)(); /* Typecast address 0 to pointer and call */
Here integer is typecast-ed and called at the same time. This function pointer definition, typecasting etc might be difficult to read for many. Because of this code may be less readable. To avoid this we may use the typedef functionality to define new types as below.
typedef void (*typFPtr)(void); /* Define new type typFPtr as pointer to a function */
typFPtr pSoftReset = (typFPtr)0; /* Assign address 0 */
pSoftReset(); /* Call using pointer */
In order to avoid confusion and improve readability, it is better to define new types and use it instead of directly using the function prototype. However, please note that this may also cause some confusion as the '*' is missing in declaration of variable and typecast. Alternately, it can also be done as below.
typedef void (typFN)(void); /* Define new type typFN as pointer to a function */
typFN *pSoftReset = (typFN *)0; /* Define pointer to function and Assign address 0 */
pSoftReset(); /* Call using pointer */

To conclude, definition and use of complex function pointers can be achieved by using typedef. Some examples are mentioned below.
 /* Below definiton is a function pointer fp which
  * will accept a pointer to a function which takes
  * pointer to int as argument, returns void and 
  * another int as second parameter and returns a
  * function pointer which takes int as argument
  * and returns pointer to int */
 int *(*((*fp)(void (*)(int*), int *)))(int);
 
 /* Uning typedef it can be simplified as below */
 typedef int *typFun_pint_int(int);
 typedef void typFun_void_pint_int(int*);
 
 typFun_pint_int * fp_simplified(typFun_void_pint_int *, int *);
 /* Here it is clear what is the return type
    and what are the arguments */
In my next post, I will list some examples of using function pointers. Initially, I thought of adding it here. But, it is too late for me now. So thought of writing it as another post.

No comments :

Post a Comment