Function Pointers and Callbacks C/C++
Function pointers can be passed as arguments to functions and then a function that would receive a function pointer as an argument can call back the function that this pointer will point to.
Example
#include <iostream>
using std::cout;
using std::endl;
void A()
{
cout << "Hello World " << endl;
}
void B(void (*ptr)()) // function Pointer as Argument
{
ptr(); // Call-Back Function that "ptr" points to
// Call to whatever function it is pointing too
}
int main()
{
void (*p)() = A; // Function Pointer (points to a function) initialize with Address of A
B(p); // Pass function pointer
}
Output:
Hello World
Function A is getting executed, through this callback
Can Also write Code like this
#include <iostream>
using std::cout;
using std::endl;
void A()
{
cout << "Hello World " << endl;
}
void B(void (*ptr)()) // function Pointer as Argument
{
ptr(); // Call-Back Function that "ptr" points to
// Call to whatever function it is pointing too
}
int main()
{
B(A);
}
Output:
Hello World
Question
What is the point of calling A indirectly through B in this Code?
Lets use BubbleSort:
#include <iostream>
using std::cout;
using std::endl;
void BubbleSort(int *A, int n)
{
int i,j, temp;
for (i = 0; i< n; i++ )
{
for (j = 0; j < n-1; j++ )
{
if (A[j] > A[j+1])
{
// Compare A[j] with A[j+1] and SWAP if needed
temp = A[j];
A[j] = A[j+1];
A[j+1] = temp;
}
}
}
}
int main()
{
int i, A[] = {3,2,1,5,6,4};
cout << "Array Before BubbleSorting: ";
for (i = 0; i <6; i++ )
{
// Print Array
cout << A[i];
}
cout << endl;
BubbleSort(A,6);
cout << "Array After BubbleSorting: ";
for (i = 0; i <6; i++ )
{
// Print Array
cout << A[i];
}
cout << endl;
}
Output:
Array Before BubbleSorting: 321564
Array After BubbleSorting: 123456
Now lets say we want to sort out list in decreasing order of the values of integers.
What changes will we make to the code?
Previous:
if (A[j] > A[j+1])
Updated:
if (A[j] < A[j+1])
With this comparison we are pushing the smaller number towards the higher index
After we make the comparison change our output is:
Array Before BubbleSorting: 321564
Array After BubbleSorting: 654321
Sometimes we want to sort in increasing order and sometimes we want to sort in decreasing order
How can we accomplish this? (without writing duplicate code)
There are multiply ways:
In order to avoid writing duplicate code we can pass flag to our bubblesort function.
Another Approach:
Our Sort function will take a function pointer as an arguemnt
compare
#include <iostream>
using std::cout;
using std::endl;
// Callback function should compare two integers and should return 1 if first element
// Has higher rank, 0 if elements are equal and -1 if second element has higher rank
int compare(int a, int b)
{
if ( a > b){
return 1;
}
else{
return -1;
}
}
void BubbleSort(int *A, int n, int (*compare)(int,int))
{
int i,j, temp;
for (i = 0; i< n; i++ )
{
for (j = 0; j < n-1; j++ )
{
if (compare(A[j], A[j+1]) > 0)
{ // Compare A[j] with A[j+1] and SWAP if needed
temp = A[j];
A[j] = A[j+1];
A[j+1] = temp;
}
}
}
}
int main()
{
int i, A[] = {3,2,1,5,6,4};
BubbleSort(A,6, compare);
for (i = 0; i <6; i++ )
{
cout << A[i] << " ";
}
cout << endl;
}
Output:
1 2 3 4 5 6
If we change our compare function
int compare(int a, int b)
{
if ( a > b){
return -1;
}
else{
return 1;
}
}
After Changing our compare function our output will be:
6 5 4 3 2 1
- We can have one call-back function for each ranking mechanism
Another Example
int A[] = {-31,22,-1,50,-6,4}; // {-1,-4,-6,22,-31,50}
We want to increase in the order of absolute value of integers, so the negative sign will not matter and we will just take a MOD and then compare
To be able to sort we will have to write another comparison function, we will add another function called absolute_compare
#include <iostream>
using std::cout;
using std::endl;
#include <math.h>
// Callback function should compare two integers and should return 1 if first element
// Has higher rank, 0 if elements are equal and -1 if second element has higher rank
int compare(int a, int b)
{
if ( a > b){
return -1;
}
else{
return 1;
}
}
int absolute_compare(int a, int b)
{
if(abs(a) > abs(b))
{
return 1;
}
else{
return -1;
}
}
void BubbleSort(int *A, int n, int (*compare)(int,int))
{
int i,j, temp;
for (i = 0; i< n; i++ )
{
for (j = 0; j < n-1; j++ )
{
if (compare(A[j], A[j+1]) > 0)
{ // Compare A[j] with A[j+1] and SWAP if needed
temp = A[j];
A[j] = A[j+1];
A[j+1] = temp;
}
}
}
}
int main()
{
int i, A[] = {-31,22,-1,50,-6,4}; // {-1,-4,-6,22,-31,50}
BubbleSort(A,6, absolute_compare);
for (i = 0; i <6; i++ )
{
cout << A[i] << " ";
}
cout << endl;
}
Output:
-1 4 -6 22 -31 50
The elements are sorted in increasing order of their absolute values.
Built in Libaries