CFunction Pointers

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
The parentheses around the name are not optional
`int (*compare)(int, int);` declares `compare` as a pointer to a function taking two `int`s and returning `int`. Drop the parentheses and `int *compare(int, int);` means something completely different: a function named `compare` that returns `int *`. The parentheses around `*compare` are what make it a pointer to a function rather than a function returning a pointer.

C
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

C
#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
No & required (but allowed)
A function name used as a value decays to its address, just like an array decays to a pointer to its first element. `op = add;` and `op = &add;` do the same thing; both styles are common in real code.
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.

C
#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 *name are 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).

  • qsort and similar library functions use a function pointer parameter so the same code can operate on any data type or ordering.