CodingBison

Since pointers are used to locate content at a given address, pointers can also be made to point to the address of a functions since functions have addresses as well. In other words, we can use pointers to pass name of functions. This method can be useful for cases, where we have a set of functions and we need to decide the right function during the run-time.

You might be wondering what happens when we have inline functions since inline functions do not have addresses. Would function pointers still work? Well, the good news is that a compiler would create an out-of-line instance of the inline function, if it sees that there is a function pointer pointing to it. Long story short, it would still work.

As usual, let us write a simple example to put our understanding to test. We provide below an example that uses a pointer to point to various functions.

 #include <stdio.h>

 int subtract(int x, int y) {
     return (x-y);
 }

 int add(int x, int y) {
     return (x+y);
 }

 int multiply(int x, int y) {
     return (x*y);
 }

 int divide(int x, int y) {
     if ( y != 0)
         return (x/y);
     else
         printf("Division by zero is not allowed\n");
     return 0;
 }

 int main () {
     int ((*func)(int, int));
     int a = 100;
     int b = 10;

     func = add;
     printf("Addition Result is %d\n", func(a,b));

     func = subtract;
     printf("Subtraction Result is %d\n", func(a,b));

     func = multiply;
     printf("Multiplication Result is %d\n", func(a,b));

     func = divide;
     printf("Division Result is %d\n", func(a,b));
     return 0;
 }

In the above example, pointer func is a function pointer and the list of arguments taken by the function is defined. Please pay close attention to the declaration of function pointer -- the function pointer is defined such that it retains its signature, "((*func)(int,int)" and the starting "int" means that it returns an int. A function pointer can point to a function if and only if the signature of the function is same as that of the function pointer.

We use func to point to add(), subtract(), multiply(), and divide() functions. These functions have the same argument signature, and so the pointer func can point to any one of them. However, if a function were to have different a argument signature, then the func pointer cannot point to that function.

Here is the output, when we run the above program:

 Addition Result is 110 
 Subtraction Result is 90 
 Multiplication Result is 1000 
 Division Result is 10 

In fact, if we wanted to do too much, then we can even define an array of function pointers. The advantage here would be that, we do not have to point the pointer func again and again to different functions. We initialize the function array at the beginning to appropriate functions and we should be all set!

Let us modify the earlier program to use a function array. To avoid duplication, we don't keep the definition of functions, add, subtract, multiply, and divide in this example. Notice the definition of the function pointer array, func, such that it now contains LEN_BINARY_OPERATIONS to specify the array size. The output for this code is same as before, so we omit it.

 #include <stdio.h>

 enum binary_operations {
     ADD,
     SUBTRACT,
     MULTIPLY,
     DIVIDE,
     LEN_BINARY_OPERATIONS,
 };

 void main () {
     int ((*func[LEN_BINARY_OPERATIONS])(int, int));
     int a = 100;
     int b = 10; 

     func[ADD] = add;
     func[SUBTRACT] = subtract;
     func[MULTIPLY] = multiply;
     func[DIVIDE] = divide;

     printf("Addition Result is %d\n", (func[ADD])(a,b));
     printf("Subtraction Result is %d\n", func[SUBTRACT](a,b));
     printf("Multiplication Result is %d\n", func[MULTIPLY](a,b));
     printf("Division Result is %d\n", func[DIVIDE](a,b));
     return 0;
 }

Accessing functions through pointers may sound awesome (and in many cases, it is!), but overusing it can seriously ruin code-readability. This is because, we can have a pointer pointing to one function at one time and yet another function at another time. All of this would make the reader focus more on the flow of function pointers instead of the actual application logic, and likely leave him confused. So, it is one of those powers that we should use as little as possible. When in doubt, avoid using function pointers -- it would go a long way in making your code readable and would do everyone good!





comments powered by Disqus