devnotes.

Function Pointers

Functions have addresses just like variables do, and C lets you store that address in a function pointer — a variable that can hold, pass around, and call a function indirectly.

#include <stdio.h>

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

typedef int (*Operation)(int, int); // named type for "function taking (int,int), returning int"

int compute(Operation op, int a, int b) {
    return op(a, b);   // calls whichever function was passed in
}

int main(void) {
    printf("%d\n", compute(add, 5, 3));       // 8
    printf("%d\n", compute(subtract, 5, 3));  // 2
    return 0;
}

The syntax int (*Operation)(int, int) reads as "a pointer to a function taking two ints and returning int" — the parentheses around *Operation are required, since without them it would declare a function returning int* instead of a pointer to a function. A typedef like this makes function pointer types far more readable wherever they're used repeatedly.

Function pointers are the classic C mechanism for callbacks — passing behavior, not just data, into another function. The standard library's own qsort function uses exactly this pattern, taking a comparator function pointer so it can sort any data type according to caller-supplied logic:

int compareInts(const void *a, const void *b) {
    return (*(const int*)a - *(const int*)b);
}

int nums[] = {5, 2, 8, 1};
qsort(nums, 4, sizeof(int), compareInts);
Function Pointers in C Explained | DevNotes