Function Pointers and Callbacks C/C++

4 minute read

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


Updated: