Function Pointers in C
Store functions in variables! Pass functions as arguments, create callbacks, and build flexible code.
Track Your Progress
Sign in to save your learning progress
What You Will Learn
- ✓Declare function pointers
- ✓Pass functions as arguments
- ✓Create callback functions
- ✓Use function pointer arrays
01What is a Function Pointer?
Simple Definition
A function pointer is a variable that stores the memory address of a function. Just like regular pointers store addresses of variables, function pointers store addresses of functions!
Visual: Regular Pointers vs Function Pointers
Regular Pointer
int *ptr
int x = 42
Points to a variable
Function Pointer
int (*fp)()
int add() {...}
Points to a function
Why Use Function Pointers?
Callbacks
Pass a function to another function to be called later. Used in event handlers, sorting, etc.
Dynamic Behavior
Choose which function to call at runtime. Like a menu: user picks option → call matching function.
State Machines
Each state has a different handler function. Current state pointer determines behavior.
Plugin Systems
Load functions at runtime. Extensible architecture without recompiling.
Real-World Example
The C standard library's qsort() function uses a function pointer to let YOU define how to compare elements. This makes it work with any data type - integers, strings, structs, anything!
02Function Pointer Syntax
Declaration Syntax
return_type (*pointer_name)(parameter_types);
The parentheses around *pointer_name are important!
1#include <stdio.h>23// A simple function4int add(int a, int b) {5 return a + b;6}78int subtract(int a, int b) {9 return a - b;10}1112int main() {13 // Declare a function pointer14 // It can point to any function that:15 // - Returns int16 // - Takes two int parameters17 int (*operation)(int, int);18 19 // Point to 'add' function20 operation = add; // or: operation = &add;21 22 // Call through pointer23 int result = operation(10, 5);24 printf("add(10, 5) = %d\n", result);25 26 // Point to 'subtract' function27 operation = subtract;28 29 result = operation(10, 5);30 printf("subtract(10, 5) = %d\n", result);31 32 return 0;33}add(10, 5) = 15
subtract(10, 5) = 5
03Callback Functions
What is a Callback?
A callback is a function passed to another function as an argument. The receiving function can then "call back" to it!
1#include <stdio.h>23// Callback function type for processing array elements4void applyToArray(int* arr, int size, int (*callback)(int)) {5 for (int i = 0; i < size; i++) {6 arr[i] = callback(arr[i]); // Apply callback to each element7 }8}910// Functions to use as callbacks11int doubleValue(int x) {12 return x * 2;13}1415int square(int x) {16 return x * x;17}1819int addTen(int x) {20 return x + 10;21}2223void printArray(int* arr, int size) {24 for (int i = 0; i < size; i++) {25 printf("%d ", arr[i]);26 }27 printf("\n");28}2930int main() {31 int numbers[] = {1, 2, 3, 4, 5};32 int size = 5;33 34 printf("Original: ");35 printArray(numbers, size);36 37 // Apply 'double' callback38 applyToArray(numbers, size, doubleValue);39 printf("Doubled: ");40 printArray(numbers, size);41 42 // Reset and apply 'square'43 int nums2[] = {1, 2, 3, 4, 5};44 applyToArray(nums2, size, square);45 printf("Squared: ");46 printArray(nums2, size);47 48 // Reset and apply 'addTen'49 int nums3[] = {1, 2, 3, 4, 5};50 applyToArray(nums3, size, addTen);51 printf("Add 10: ");52 printArray(nums3, size);53 54 return 0;55}Original: 1 2 3 4 5
Doubled: 2 4 6 8 10
Squared: 1 4 9 16 25
Add 10: 11 12 13 14 15
04Array of Function Pointers
1#include <stdio.h>23int add(int a, int b) { return a + b; }4int subtract(int a, int b) { return a - b; }5int multiply(int a, int b) { return a * b; }6int divide(int a, int b) { return b != 0 ? a / b : 0; }78int main() {9 // Array of function pointers10 int (*operations[4])(int, int) = {add, subtract, multiply, divide};11 char* names[] = {"Add", "Subtract", "Multiply", "Divide"};12 13 int a = 20, b = 5;14 15 printf("Calculator Demo (a=%d, b=%d):\n\n", a, b);16 17 for (int i = 0; i < 4; i++) {18 int result = operations[i](a, b); // Call through array19 printf("%s: %d\n", names[i], result);20 }21 22 // Menu-driven selection23 printf("\nEnter operation (0=Add, 1=Sub, 2=Mul, 3=Div): ");24 int choice = 0; // Simulating user input25 printf("%d\n", choice);26 27 printf("Result: %d\n", operations[choice](a, b));28 29 return 0;30}Calculator Demo (a=20, b=5):
Add: 25
Subtract: 15
Multiply: 100
Divide: 4
05Cleaner Syntax with typedef
Function pointer syntax is complex. Use typedef to make it cleaner!
Without typedef (hard to read):
int (*operation)(int, int);
With typedef (clean):
Operation op;
1#include <stdio.h>23// Define a type for our function pointer4typedef int (*Operation)(int, int);56int add(int a, int b) { return a + b; }7int multiply(int a, int b) { return a * b; }89// Now function parameters are clean!10int calculate(int a, int b, Operation op) {11 return op(a, b);12}1314int main() {15 // Clean variable declaration16 Operation myOp = add;17 printf("add: %d\n", myOp(10, 5));18 19 myOp = multiply;20 printf("multiply: %d\n", myOp(10, 5));21 22 // Pass to function easily23 printf("calculate with add: %d\n", calculate(10, 5, add));24 printf("calculate with multiply: %d\n", calculate(10, 5, multiply));25 26 return 0;27}add: 15
multiply: 50
calculate with add: 15
calculate with multiply: 50
06Real Example: qsort() from Standard Library
The Power of Function Pointers
The C standard library's qsort() function is a perfect example of why function pointers are powerful. It can sort any type of data because YOU provide the comparison function!
qsort() Signature
void qsort(
void *base, // Array to sort
size_t num, // Number of elements
size_t size, // Size of each element
int (*compare)(const void*, const void*) // Your comparison function!
);
The last parameter is a function pointer — you decide how elements are compared!
1#include <stdio.h>2#include <stdlib.h>3#include <string.h>45// Comparison function for ascending integers6int compareAsc(const void* a, const void* b) {7 return (*(int*)a - *(int*)b);8}910// Comparison function for descending integers11int compareDesc(const void* a, const void* b) {12 return (*(int*)b - *(int*)a);13}1415// Comparison function for strings16int compareStrings(const void* a, const void* b) {17 return strcmp(*(char**)a, *(char**)b);18}1920void printArray(int arr[], int n) {21 for (int i = 0; i < n; i++) printf("%d ", arr[i]);22 printf("\n");23}2425int main() {26 // Sort integers ascending27 int nums[] = {5, 2, 8, 1, 9, 3};28 int n = sizeof(nums) / sizeof(nums[0]);29 30 printf("Original: ");31 printArray(nums, n);32 33 qsort(nums, n, sizeof(int), compareAsc);34 printf("Ascending: ");35 printArray(nums, n);36 37 qsort(nums, n, sizeof(int), compareDesc);38 printf("Descending: ");39 printArray(nums, n);40 41 // Sort strings!42 char* names[] = {"Charlie", "Alice", "Bob", "Diana"};43 int count = 4;44 45 printf("\nNames before: ");46 for (int i = 0; i < count; i++) printf("%s ", names[i]);47 printf("\n");48 49 qsort(names, count, sizeof(char*), compareStrings);50 51 printf("Names after: ");52 for (int i = 0; i < count; i++) printf("%s ", names[i]);53 printf("\n");54 55 return 0;56}Original: 5 2 8 1 9 3
Ascending: 1 2 3 5 8 9
Descending: 9 8 5 3 2 1
Names before: Charlie Alice Bob Diana
Names after: Alice Bob Charlie Diana
!Code Pitfalls: Common Mistakes & What to Watch For
These are the most common mistakes that trip up beginners. Study them carefully to avoid hours of debugging!
Missing Parentheses Around *
The parentheses around *pointer_name are required!
WRONG:
int *func(int, int);
→ Function returning int*
CORRECT:
int (*func)(int, int);
→ Pointer to function returning int
Calling NULL Function Pointer
Always check if a function pointer is NULL before calling it!
WRONG (crashes!):
int (*fp)(int) = NULL; fp(5); // CRASH!
CORRECT:
int (*fp)(int) = NULL;
if (fp != NULL) {
fp(5);
}Mismatched Signatures
The function pointer type must exactly match the function signature!
WRONG:
int add(int a, int b); float (*fp)(int, int); // Wrong return type! fp = add; // Type mismatch
CORRECT:
int add(int a, int b); int (*fp)(int, int); // Matches! fp = add; // OK
Watch Out When Copying Code!
Common Mistakes with Function Pointers
Copying code frequently generate broken function pointer code:
- ✗Wrong parentheses: Copied code
int *fp(int)instead ofint (*fp)(int) - ✗Signature mismatches: Beginners often assign functions with wrong return types or parameters
- ✗Missing NULL checks: Beginners often dereference function pointers that could be NULL
- ✗Incorrect qsort comparators: Beginners often forget to cast void* or returns wrong comparison values
Always Understand Before Using
Function pointer syntax is tricky even for humans. Use typedef to make it clearer. Always verify the function signature matches exactly, and check for NULL before calling. Compile with -Wall -Werror to catch type mismatches.
09Frequently Asked Questions
Q:Why is the syntax for function pointers so complicated?
A: The parentheses around(*name) are needed because without them,int *fp(int) means "function returning int*", not "pointer to function." Use typedef to simplify:typedef int (*Calculator)(int, int);
Q:What is a callback function?
A: A function passed to another function to be called later. Example: qsort takes a comparison callback — you tell it HOW to compare, it handles the sorting. Callbacks allow generic, reusable code.
Q:Can I have arrays of function pointers?
A: Yes! Great for dispatch tables (menu systems, state machines). int (*ops[])(int,int) ={add, sub, mul} then ops[choice](a, b). Much cleaner than long switch statements.
Q:What's the difference between fp and &fp for functions?
A: For functions, both are equivalent! A function name automatically converts to a pointer to itself (like arrays).fp = add andfp = &add do the same thing.
Q:Where are function pointers used in real code?
A: Everywhere! qsort/bsearch (stdlib), signal handlers, GUI callbacks, plugin systems, virtual method tables (OOP in C), state machines, and more. They enable runtime flexibility and polymorphism in C.
09Summary
Key Takeaways
- •Function pointer: Variable storing function address
- •Syntax: return_type (*name)(params)
- •Callbacks: Pass functions as arguments
- •typedef: Makes syntax much cleaner
- •Arrays: Store multiple function pointers
- •qsort(): Classic real-world example
Quick Reference
Declare
int (*fp)(int, int);
Assign
fp = add;
Call
result = fp(5, 3);
typedef
typedef int (*Op)(int, int);
10Real-World Use Cases
Callback Functions
Event handlers, timers, and async operations use function pointers as callbacks. You register your function, and the library calls it when the event occurs.
Plugin Systems
Load shared libraries at runtime with dlsym() and store the function addresses in function pointers. This enables extensible applications.
State Machines
Function pointers are excellent for implementing state machines. Each state is a function, and the current state is stored as a function pointer. Transitioning states just means changing which function the pointer references.
Test Your Knowledge
Related Tutorials
C Preprocessor Directives
Code that runs before compilation! Learn #include, #define macros, and conditional compilation with #ifdef.
Bitmasks and Bit Manipulation
Work with individual bits! Set, clear, toggle, and check bits. Implement permission systems and flags efficiently.
Pointers in C
The most powerful feature in C! Pointers store memory addresses. Learn what they are, why they matter, and how to use them safely.
Have Feedback?
Found something missing or have ideas to improve this tutorial? Let us know on GitHub!