C Function Pointers

In C, functions are stored in memory just like variables. A function pointer is a pointer that stores the memory address of a function instead of the address of a data variable. Once you have a function pointer, you can use it to call the function it points to.

Function pointers make programs flexible — they let you decide at runtime which function to execute, pass functions as arguments to other functions, and build tables of functions for fast dispatching.

Why Use Function Pointers?

Think of a TV remote. A single "OK" button does different things depending on what you select: it can play a movie, open an app, or confirm a setting. Function pointers work the same way — one pointer can call different functions at different times.

  • Implement callback functions (functions passed to other functions)
  • Build menus or command dispatch tables
  • Replace long switch statements
  • Enable plugin-style architecture

Declaring a Function Pointer

Syntax

return_type (*pointer_name)(parameter_types);

The parentheses around *pointer_name are essential. Without them, the statement would declare a function returning a pointer, not a pointer to a function.

int (*funcPtr)(int, int);   // pointer to a function that takes two ints and returns int
void (*action)();           // pointer to a function that takes nothing and returns void
float (*calculate)(float);  // pointer to a function that takes float and returns float

Basic Example: Assigning and Calling a Function Pointer

#include <stdio.h>

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

int main()
{
    int (*funcPtr)(int, int);   // declare function pointer
    funcPtr = add;              // assign function address (no & needed for functions)

    int result = funcPtr(5, 3); // call the function through the pointer

    printf("Result: %d\n", result);   // Output: Result: 8

    return 0;
}

Visual Diagram


Function 'add' stored at memory address: 0x4005f0

funcPtr → [0x4005f0] → add(5, 3) → returns 8

Calling funcPtr(5, 3) is the same as calling add(5, 3)

Calling Styles for Function Pointers

Both styles below work. The first is cleaner and more commonly used.

funcPtr(5, 3);     // style 1 — clean (recommended)
(*funcPtr)(5, 3);  // style 2 — explicit dereference (also valid)

Switching Functions at Runtime

A function pointer can point to different functions at different times. This is its main power.

#include <stdio.h>

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

int main()
{
    int (*operation)(int, int);
    int x = 10, y = 4;

    operation = add;
    printf("Add      : %d\n", operation(x, y));   // Output: 14

    operation = subtract;
    printf("Subtract : %d\n", operation(x, y));   // Output: 6

    operation = multiply;
    printf("Multiply : %d\n", operation(x, y));   // Output: 40

    return 0;
}

Passing a Function Pointer to Another Function (Callback)

A common use of function pointers is to pass a function as an argument to another function. This is called a callback.

#include <stdio.h>

int square(int n) { return n * n; }
int cube(int n)   { return n * n * n; }

void applyAndPrint(int value, int (*transform)(int))
{
    int result = transform(value);
    printf("Result: %d\n", result);
}

int main()
{
    applyAndPrint(4, square);   // Output: Result: 16
    applyAndPrint(3, cube);     // Output: Result: 27
    return 0;
}

Array of Function Pointers (Dispatch Table)

An array of function pointers is like a menu of options — index into the array to choose which function to call. This replaces long switch-case blocks.

#include <stdio.h>

void optionA() { printf("You selected Option A\n"); }
void optionB() { printf("You selected Option B\n"); }
void optionC() { printf("You selected Option C\n"); }

int main()
{
    void (*menu[3])() = {optionA, optionB, optionC};
    int choice = 1;   // user picks option B (index 1)

    menu[choice]();   // Output: You selected Option B

    // Loop through all options
    for (int i = 0; i < 3; i++)
    {
        menu[i]();
    }

    return 0;
}

Output:

You selected Option B
You selected Option A
You selected Option B
You selected Option C

Using typedef to Simplify Function Pointer Declarations

Function pointer syntax can get complex. typedef creates a shorter alias that makes declarations much cleaner.

#include <stdio.h>

typedef int (*MathFunc)(int, int);   // MathFunc is now an alias for this pointer type

int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }

void compute(int x, int y, MathFunc fn)
{
    printf("Result: %d\n", fn(x, y));
}

int main()
{
    MathFunc f = add;       // clean declaration using typedef
    compute(6, 7, f);       // Output: Result: 13

    f = multiply;
    compute(6, 7, f);       // Output: Result: 42

    return 0;
}

Function Pointers and qsort()

The standard library function qsort() uses a function pointer to sort any array. You provide a comparison function, and qsort() calls it to determine the order of elements.

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

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

int main()
{
    int nums[] = {42, 7, 19, 3, 55};
    int size = 5;

    qsort(nums, size, sizeof(int), ascending);

    for (int i = 0; i < size; i++)
        printf("%d ", nums[i]);   // Output: 3 7 19 42 55

    printf("\n");
    return 0;
}

Common Mistakes with Function Pointers

MistakeWrongCorrect
Missing parentheses in declarationint *ptr(int, int)int (*ptr)(int, int)
Mismatched signatureAssigning void func() to int (*fp)()Signatures must match exactly
Calling NULL pointerfp() when fp == NULLCheck if (fp != NULL) first

Summary

A function pointer stores the memory address of a function and allows calling that function through the pointer. The declaration uses the syntax return_type (*pointer_name)(parameter_types). Function pointers make it possible to switch which function runs at runtime, pass functions as arguments to other functions (callbacks), and build dispatch tables that replace long switch-case blocks. The standard library itself uses function pointers — qsort() being the classic example. Using typedef simplifies complex function pointer declarations into readable type aliases. Function pointers are a key step toward understanding advanced patterns in C and eventually C++.

Leave a Comment

Your email address will not be published. Required fields are marked *