Function pointers in C can be tricky for beginners, but they are one of the most powerful features of the language. They allow you to treat functions as first-class entities—passing them as arguments, storing them in variables, and invoking them dynamically.
What is a Function Pointer? #
When you define a function in C, the compiler allocates a block of memory for the function code. The starting address of that block is the function’s pointer (entry address).
Just like an array name represents its base address, a function name represents its memory address. This means you can assign a function’s address to a pointer and call the function indirectly.
Declaring a Function Pointer #
Declaring a function pointer is similar to declaring a variable pointer.
For example:
int getData(int a, int b);     // Function declaration
int (*p)(int a, int b);        // Function pointer declaration
⚠️ Note: Parentheses around
*pare required due to operator precedence. Without them,int *p(int a, int b);would declare a function returning int* instead of a pointer to a function.
Example: Calling Functions via Pointers #
Let’s start with a simple example to see how function pointers work.
#include "stdio.h"
void PrintWelcome() {
    printf("Hello, welcome\n");
}
int main() {
    // Direct function call
    PrintWelcome();
    // Indirect call using a function pointer
    void (*p)() = PrintWelcome;
    (*p)();
    return 0;
}
Output #
Hello, welcome
Hello, welcome
Both calls produce the same result. The key rule: 👉 The function pointer’s type must match the target function’s type.
Why Use Function Pointers? #
Function pointers provide flexibility. They enable techniques such as:
- Dynamic function selection at runtime
- Callback mechanisms
- Table-driven programming (jump tables)
Let’s see a practical case.
Example: Function Pointers with switch 
    
    
    
        #
            
    
Suppose the user inputs 1, 2, or 3:
- 1: return the maximum of two integers
- 2: return the minimum
- 3: return their sum
We can solve this elegantly using function pointers.
#include "stdio.h"
#include "stdlib.h"
// Three operations
int GetMax(int a, int b) { return a > b ? a : b; }
int GetMin(int a, int b) { return a < b ? a : b; }
int GetSum(int a, int b) { return a + b; }
// Function handler using a function pointer
int dataHandler(int a, int b, int (*pfunk)(int, int)) {
    return pfunk(a, b);
}
int main() {
    int a = 10, b = 20;
    int cmd, ret;
    int (*pfunk)(int, int);
    printf("Enter 1 for max, 2 for min, 3 for sum: ");
    scanf("%d", &cmd);
    switch (cmd) {
        case 1:
            printf("Maximum: ");
            pfunk = GetMax;
            break;
        case 2:
            printf("Minimum: ");
            pfunk = GetMin;
            break;
        case 3:
            printf("Sum: ");
            pfunk = GetSum;
            break;
        default:
            printf("Invalid input\n");
            exit(-1);
    }
    ret = dataHandler(a, b, pfunk);
    printf("ret = %d\n", ret);
    return 0;
}
Example Run #
$ ./test
Enter 1 for max, 2 for min, 3 for sum: 1
Maximum: ret = 20
$ ./test
Enter 1 for max, 2 for min, 3 for sum: 2
Minimum: ret = 10
$ ./test
Enter 1 for max, 2 for min, 3 for sum: 3
Sum: ret = 30
Key Notes on Function Pointers #
- Always use parentheses when declaring (int (*pfunk)(int, int)).
- The pointer’s signature must match the target function’s return type and parameters.
- Argument names in declarations are optional:
int (*pfunk)(int, int);   // valid
is equivalent to:
int (*pfunk)(int data1, int data2);
Conclusion #
Function pointers in C are powerful tools that allow dynamic behavior in programs. They are essential in areas such as:
- Event-driven systems
- Callback implementations
- Low-level OS or driver code
- Table-driven command execution
By mastering function pointers, you gain a deeper understanding of C’s flexibility and runtime capabilities.
