Function pointer in C

In this ongoing C programming tutorial series, we learnt many concepts related to function and pointers. Let us give a quick recall.

A function is a collection of statements grouped together to perform a task. Function encapsulates behaviour and allows us to write modular and reusable code. Instead of writing same code to perform an action ‘A’ repeatedly, we call a function that encapsulates action ‘A’.

However, there happens situation when we want same function to exhibit different behaviour for different situations. Means behaviour of a function is determined dynamically. For example, consider a sorting function qsort(). The qsort() function exhibit a behaviour of sorting data in ascending or descending order. Instead of binding the sorting behaviour with qsort() function, we can pass the sorting behaviour using a function pointer to qsort() function. Got confused, hold you breath and read further I will cover function pointer from a beginner point.

What is function pointer?

Function pointer is a special pointer that points to a function. Yes a pointer can point to any object in C. Instead pointing at variable, a function pointer points at executable code.

We use function pointer to call a function or to pass reference of a function to another function. Which means you can pass a function to another function (using function pointers).

Syntax to declare function pointer

return-type (* function_pointer_name) (parameter_list_type);
  • return-type: Return type of a function.
  • function_pointer_name: Valid C identifier that specifies name of function pointer.
  • parameter_list_type: List of parameter types the function accepts.

Note: Function pointer declaration defines prototype of functions it can point. Where function pointer return type must match function return type to which it will point. Similarly parameter type must match list of parameter types of a function to which it will point.

How to declare function pointer?

int (* arith)(int, int);

The above statement declares a function pointer arith. It can point to all functions whose return type is int and accepts two integer parameters.

How to initialize function pointer?

Function pointer points to a function, means it accepts address of a function. To get address of any object in C we use address & operator. Similarly, you can also use & operator to get the address of a function.

For example,

int add(int num1, int num2)
{
    return (num1 + num2);
}

int main()
{
    int (* arith)(int, int);	// Function pointer declaration

    arith = &add; 			   // Function pointer initialization

    return 0;
}

Note: The function signature must match function pointer signature. In our case, function signature is int (int, int) and function pointer signature is int (int, int).

You can also use function name directly to get the function memory address. Hence the statement arith = &add; is equivalent to arith = add;

How to call a function using function pointer?

Calling or invoking a function using function pointer is similar to access value pointed by a pointer. To access value pointed by a pointer we use dereferencing * operator.

Syntax to call a function using function pointer

(* function-pointer)(function-parameters);

Example to call a function using function pointer

(* arith)(10, 20);

When calling a function using function pointer use of dereferencing * operator is optional. Hence (* arith)(10, 20); is equivalent to arith(10, 20);

Example program to use function pointer

Write a C program to demonstrate working of a function pointer.

#include <stdio.h>

/* Function declarations */
int add(int, int);
int sub(int, int);

int main()
{
    int sum, diff;
    int (* arith)(int, int);    // Function pointer declaration

    arith = add;                // Function pointer arith points to add()
    sum   = arith(10, 20);      // Call add() using function pointer

    arith = sub;                // Function pointer arith points to sub()
    diff  = arith(100, 30);     // Call sub() using function pointer
 
    printf("10+20  => %d\n", sum);
    printf("100-30 => %d\n", diff);

    return 0;
}

/* Function definition */
int add(int num1, int num2)
{
    return (num1 + num2);
}

int sub(int num1, int num2)
{
    return (num1 - num2);
}

Output –

10+20  => 30
100-30 => 70

How to pass function pointer as parameter to function

The above example explains basic working of a function pointer. Let us switch to our original qsort() function to sort an array. The function exhibits two behaviour, sorting array in ascending order or descending order.

Instead of binding sorting behaviour to qsort() function, we will pass sorting behaviour using function pointer. Which means instead of defining the logic to arrange two elements within function, we will pass this logic (behaviour) to qsort() function as a parameter.

Suppose a function int sort_ascending(int, int), that accepts two integer parameters and returns an integer. The integer returned defines which of the two integer parameters are greater. We will pass the reference of sort_ascending to qsort() function. qsort() function will internally use sort_ascending function to determine the order of arrangement of two elements.

qsort() function is defined in stdlib.h header file. General syntax of qsort() function is –

void qsort(void *, size_t, size_t, int (*)(const void*, const void*));

It accepts an array as first argument, size of the array as second argument, size of each element as third argument and a function pointer that specifies the sorting behaviour.

To implement the sorting behaviour we need a function that returns an integer and accepts two const void * pointer type arguments.

Learn more –

#include <stdio.h>
#include <stdlib.h>

#define SIZE 10  // Maximum array size

void printArray(int *, int);

/* Sorting behaviour declarations */
int sort_ascending(const void *, const void *);
int sort_descending(const void *, const void *);

int main()
{
    int array[SIZE] = {20, 80, 100, 50, 40, 30, 60, 90, 70, 10};

    int (* compare)(const void *, const void *);    // Function pointer

    printf("Unsorted array");
    printArray(array, SIZE);

    compare = sort_ascending;	// compare now points to sort_ascending function

    // Call qsort() function with ascending sorting behaviour
    qsort(array, SIZE, sizeof(int), compare);

    printf("\n\nAscending sorted array");
    printArray(array, SIZE);

    compare = sort_descending;	// compare now points to sort_descending function

    // Call qsort() function with descending sorting behaviour
    qsort(array, SIZE, sizeof(int), compare);

    printf("\n\nDescending sorted array");
    printArray(array, SIZE);

    return 0;
}

/**
 * The function accepts two void pointers. It internally 
 * converts void pointer to integer and returns a
 * negative value if num1 < num2
 * positive value if num1 > num2
 * and zero value if num1 ==num2
 */
int sort_ascending(const void * num1, const void * num2)
{
    return (*(int *)num1) - (*(int *)num2);
}


/**
 * The function accepts two void pointers. It internally 
 * converts void pointer to integer and returns a
 * negative value if num1 > num2
 * positive value if num1 < num2
 * and zero value if num1 ==num2
 */
int sort_descending(const void * num1, const void * num2)
{
    return (*(int *)num2) - (*(int *)num1);
}


/**
 * printArray accepts pointer to an array and size of the 
 * array. It prints all elements of the given array.
 */
void printArray(int * array, int size)
{
    int i;
    printf("\nArray elements are: ");
    for(i=0; i<size; i++)
    {
        printf("%d, ", *(array + i));
    }
}

Output –

Unsorted array
Array elements are: 20, 80, 100, 50, 40, 30, 60, 90, 70, 10,
Ascending sorted array
Array elements are: 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
Descending sorted array
Array elements are: 100, 90, 80, 70, 60, 50, 40, 30, 20, 10,