Tuesday, 7 February 2012

How the Function Pointers are used in real time applications?

What is Function Pointer?
         Function Pointer are pointers i.e. variable, which point to the address of a function. 
One can use them to replace switch/if-statements, to realize your own late-binding or to implement callbacks. 
Function pointers will call  functions during run time. This means the functions are determined during run time, this is called Late Binding or Run time polymorphism (as Virtual Functions).

Virtual functions also use Late binding. In the case of Virtual function, the base class member function should be overridden by derived class member function.This is also called function over riding.

What is the syntax for function Pointer?

returnType  (*function Pointer ) (parameter1, parameter2);

Important point to remember (when you are using function pointer): 

Function pointers always point to a function having a specific signature. Thus, all functions used with the same function pointer must have the same parameters and return type

The function Pointer and function whose address is pointed should have same signature.
Signature means Return Type, Number of parameters and parameters data type of function should be same.

For example:
 // Function pointer "ptr_func" takes two integers as parameters and return integer value.
1. int ( *ptr_func)(int a, int b);

// Function whose address is pointed by the function pointer
2. int plus(int a, int b);


If you observe, the both functions 1 and 2 has same signature. It means both functions has same return type and parameters (data type , No.of Parameters) .


How to Declare function Pointer in C and C++? 
C
int (*ptr_func)(int a, int b);
C++ 
int (BaseClass:: *ptr_func)(int a, int b); 

How to initialize or define the function pointer to NULL?
C
int (*ptr_func)(int a, int b) = NULL;
C++
int (BaseClass:: *ptr_func)(int a, int b) = NULL


How to Assign an Address to a Function Pointer?
C
int add(int a , int b );
int (*ptr_func)(int , int ) = NULL; 

There are two ways of assign an address to a function pointer. 

First way :   
ptr_func = add;  // short Form 
Second way : 
/* correct Assignment using address of the function */
ptr_func = &add;
C++ 
int (BaseClass:: *ptr_func)(int a, int b) = NULL;
class Baseclass
{
public:
   int add(int a, int b)

    { cout << "Baseclass::add"<< endl; return(a+b);
    };
 
};
// correct assignment using address operator
ptr_func = &Baseclass::add;


How to Compare Function Pointers (== or =!)?
C  

You can use either == or =! to compare the function pointers.
 if(ptr_func == &add)
{

   printf("Pointer points to add\n"); }
else
   printf("Pointer not initialized!!\n");

}
C++
if(ptr_func == &Baseclass::add)
   cout << "Pointer points to Baseclass::add" << endl; 

How to call Function using Function Pointer?

C
There are two ways of calling function Pointer in C
int result1 = ptr_func(2,3); 
int result2 = (*ptr_func)(2,3);

C++ 
// Declare the Object for the BaseClass
BaseClass instance1;
// Call the function pointer with Instance1(object)
int result3 = (instance1.*ptr_func)(2,3);

// Call the function pointer with *this (address of object)
int result4 = (*this.*ptr_func)(2,3)
 
// create new object Instance2
BaseClass* instance2 = new BaseClass;
int result4 = (instance2->*ptr_func)(2,3); 
delete instance2;


How to Pass Function pointer as argument? 
The function pointer should be declared as a parameter in  any function, then the address of normal function is passed .
Please refer the below code for better understanding.
Code snippet:
int (*ptr_func)(int, int);

int add(int a, int b)
{
   return (a+b);
}
void operation(int (*ptr_func)(int, int))
{
   result = (*ptr_func)(3,4);
   cout<<"The result is\n"<<result;
}
int main()
{
    Operation(&add);
}



How to return Function Pointer?

There are two ways to Return function pointer.

First way of declaration
========================
int add(int a, int b)
{
   return (a+b);
}
/* function Pointer */
int (*ptr_func)(int a, int b);

/*  Return the address of function based on Operation */
int (*Getfunction(char operation))(int, int);

// solution: Function takes a char and returns a pointer to a
// function which is taking two int and returns a int. 

// <operation> specifies which function to return
int (*Getfunction(char operation)(int, int)
{
   if(operation == '+')
   {
      return &add;
   }
   else
   {
      return &sub;
   }
}
int main()
{
  int result;

  /* This function returns the Function address *

  ptr_func = (*Getfunction)('+'); or // Getfunction)('+');

  result  =  (*ptr_func)(2,3);

  cout<<"The result"<<result;
}
Second way:
=============
// Solution using a typedef: Define a pointer to a function which is taking  two int and returns a int
typedef int(*pt2Func)(int, int);

// Function takes a char and returns a function pointer which is defined with the typedef above. Operation specifies which function to return
pt2Func Getfunction(char operation)
{
   if(operation == '+')
      return &Plus;
   else
      return &Minus; // default if invalid operator was passed
}
int main()
{
  int result;

  /* This function returns the Function address */
  ptr_func = (*Getfunction)('+'); or // Getfunction)('+');

  result  =  (*ptr_func)(2,3);
}

How to Declare and Use array of Function Pointers?

In Real time applications, array of function pointers have been used extensively.

e.g: 
1. Let's take a example, There is a process called xyzProcess in which there are three modules Xmodule, Ymodule and Zmodule. ZModule receives the messages from other process or system via sockets.
2.After decoding these message in Zmodule and take a decision to send these messages to either Xmodule or Ymodule.
3.These Module functions are called dynamically using a call back functions(function Pointers).

Simple way to declare a array of function pointers:
C
It uses a typedef  -> typedef  int (*ptrfunc)(int, int);

First way using the typedef:
// This is array with 10 pointers to functions which takes two integers and returns int.  
ptrFunc funcArray1[10] = {NULL};
//The second way directly defines the array. 
// 2nd way directly defining the array
int (*funcArray2[10])(int,int) = {NULL};
C++
// type-definition: 'ptrfunc' now can be used as type
typedef int (Baseclass::*ptrfunc)(int, int);// first way using the typedef
ptrfunc functionArray1[10] = {NULL};
Second way: 

// 2nd way of directly defining the array
 int (BaseClass::*functionArray2[10])(int, int) = {NULL};

How to assign address of functions to array of function pointers?

// assign the function's address
// assign the address of add and sub functions.
funcArray1[0] = funcArray1[1] = &add;
funcArray1[1] = funcArray2[0] = &sub;

How to call the array of function pointers?
C
// short form
 funcArray1[0](2,3) 
 // Correct way of calling
  (*funcArray1[0])(2,3) 
C++
funcionArray1[1] = functionArray2[0] = &BaseClass::add;
BaseClass instance;
cout << (instance.*funcionArray1[1])(2,3) << endl;


Example Code of simple Function Pointer:

#include<stdio.h>

/*Function Pointer */
int (*ptr_func)(int,int);

/* General Function */
/* Addition */
int add(int, int);

/* Subtraction */
int sub(int, int);

/* multiplication */
int mul(int, int);

int add(int a, int b)
{
   return (a+b);
}

int sub(int a, int b)
{
   if(a>b)
     return (a-b);
   else
     return (b-a);  
}
int mul(int a, int b)
{
   return (a*b);  
}

int main()
{
   int result1;

   /* Store the Address of add function in to Function Pointer */
   ptr_func = &add;  /* or ptr_func = add */
     
   /* call add  function */ 
   result1= (*ptr_func)(2,3);   /* or ptr_func(2,3); */

   printf("The Addition Result is : %d\n", result1);

   /* Store the address of sub function in to Function Pointer */
   ptr_func = &sub;  /* or ptr_func = sub */
    
   /* call sub  function */
   result1= (*ptr_func)(5,3);   /* or ptr_func(5,3); */

   printf("The subtraction Result is : %d\n", result1);

   /* Store the address of Mul function in to Function Pointer */
   ptr_func = &mul;  /* or ptr_func = mul */
     
   /* call Mul  function */
   result1= (*ptr_func)(2,1);   /* or ptr_func(2,1); */

   printf("The Multiplication Result is : %d\n", result1);

   return 0;
}

Note: In the above code example, the general functions and function pointer signature is same.

Example Code of Array of Function Pointers:

#include<stdio.h>
#define MAX_MODULES 2

/* Step 1 and 2 defines the array of function Pointers */

/* step 1: */
/* Typedef Function Pointer */
typedef int (*ptr_func)(int,int);

/* step 2: */
/* Define the array of Function pointers (MAX array will be 2) */
ptr_func funcArray[MAX_MODULES];
/* Define a Enum */
typedef enum
{
  XProcessModule=0,
  YProcessModule=1 
}Module;


/* Register the function in to ARRAY of Pointers using Module ID */
void registerWithZprocess(Module moduleId, int (*func_ptr)(int,int))
{
    if(!funcArray[moduleId])
    {
        funcArray[moduleId] = func_ptr;
    }
    else
    {
        printf("Module is already resigtered with Z Process:%d", moduleId);
    }       
}

/* General Function */
/* Addition */
int add(int, int);

/* Subtraction */
int sub(int, int);

int add(int a, int b)
{
   return (a+b);
}

int sub(int a, int b)
{
   if(a>b)
     return (a-b);
   else
     return (b-a);  
}

int main()
{
    int operation, result1;

    /* Registers Xprocess */
    registerWithZprocess(XProcessModule, &add);

    /* Registers Yprocess */
    registerWithZprocess(YProcessModule, &sub);

    printf("Enter the what operation to be performed\n");
    scanf("%d", &operation);

    if(operation == 0)
    {
         /* call the Add functionality */
         result1 = funcArray[XProcessModule](2,3);
    }
    else
    {
       /* call the Sub functionality */
         result1 = funcArray[YProcessModule](2,3);
    }    
   printf(" The Result of the Operation[%d] is: %d", operation, result1 );
   return 0;
}

3 comments: