Function Pointers
Functions live in memory too, and just like data, their location can be stored in a pointer. A function pointer holds the address of a function, and calling through it invokes whichever function it currently points to. This is the mechanism C uses for callbacks and a simple form of runtime polymorphism, decades before languages had first-class functions built in.
Declaring a function pointer
int (*compare)(int, int); // pointer to a function: int -> int -> int int *make_pointer(int, int); // a different thing entirely: returns int*
Assigning and calling through a function pointer
#include <stdio.h>
int add(int a, int b) {
return a + b;
}
int multiply(int a, int b) {
return a * b;
}
int main(void) {
int (*op)(int, int);
op = add; // a function name decays to its address
printf("add: %d\n", op(3, 4));
op = multiply;
printf("multiply: %d\n", op(3, 4));
return 0;
}add: 7 multiply: 12
Classic use case: qsort()
The standard library's qsort function can sort an array of any type because it does not know how to compare your elements itself — instead, you pass it a function pointer to a comparison function, and qsort calls it whenever it needs to compare two elements.
#include <stdio.h>
#include <stdlib.h>
// qsort requires this exact signature: two const void* parameters,
// returning negative/zero/positive for less-than/equal/greater-than.
int compare_ints(const void *a, const void *b) {
int int_a = *(const int *)a;
int int_b = *(const int *)b;
return int_a - int_b;
}
int main(void) {
int nums[] = {5, 2, 8, 1, 9, 3};
int count = sizeof(nums) / sizeof(nums[0]);
qsort(nums, count, sizeof(int), compare_ints);
for (int i = 0; i < count; i++) {
printf("%d ", nums[i]);
}
printf("\n");
return 0;
}1 2 3 5 8 9
qsort itself never needs to know what int_a - int_b means for your data — it only cares about the sign of the result. Swap in a different comparison function (say, one that compares struct fields, or reverses the order) and the exact same qsort call sorts completely differently, with no changes to qsort itself.
Callbacks and primitive polymorphism
Anywhere a piece of behavior needs to be a parameter — "sort using this comparison," "call this when the operation finishes," "apply this transformation to every element" — a function pointer lets C pass code as a value. This is the same idea behind callbacks in event-driven code, and it is how C simulates the kind of polymorphism that object-oriented languages provide through virtual methods and interfaces.
int (*name)(params)declares a function pointer; the parentheses around*nameare required.Assign it a function of matching signature — the function name decays to its address automatically.
Call through it with normal call syntax:
name(args).qsortand similar library functions use a function pointer parameter so the same code can operate on any data type or ordering.