Function Pointers & Callback Functions in C
🎠The Magic Remote Control Story
Imagine you have a magic remote control. But this remote is special—instead of buttons for “volume up” or “channel change,” it has empty slots where you can plug in ANY button you want!
- Want it to play music? Plug in the “music button.”
- Want it to turn on lights? Plug in the “lights button.”
- Same remote, different jobs!
That’s exactly what a function pointer is! It’s a special holder that can point to ANY function you choose, and when you press “go,” it runs that function.
📍 What is a Function Pointer?
A function pointer is a variable that stores the address of a function—just like a regular pointer stores the address of data.
Simple Analogy
Think of your school intercom system:
- The intercom (function pointer) can call ANY classroom
- Today it calls Room 101 (one function)
- Tomorrow it calls Room 205 (different function)
- Same intercom, different rooms!
The Basic Syntax
// Declaring a function pointer
return_type (*pointer_name)(parameter_types);
// Example: pointer to a function that
// takes two ints and returns an int
int (*mathOperation)(int, int);
Breaking it down:
int→ What the function gives back(*mathOperation)→ The pointer’s name (parentheses are important!)(int, int)→ What the function needs
🎯 Your First Function Pointer
Let’s see it in action with a super simple example:
#include <stdio.h>
// A simple function
int add(int a, int b) {
return a + b;
}
int main() {
// Create a function pointer
int (*operation)(int, int);
// Point it to 'add' function
operation = add;
// Use it! Same as calling add(5, 3)
int result = operation(5, 3);
printf("5 + 3 = %d\n", result);
return 0;
}
Output: 5 + 3 = 8
What just happened?
- We made an empty “slot” called
operation - We plugged the
addfunction into that slot - We used the slot to call the function!
🔄 Swapping Functions Like Magic
The real power? You can change which function it points to!
#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 (*calc)(int, int);
calc = add;
printf("10 + 5 = %d\n", calc(10, 5));
calc = subtract;
printf("10 - 5 = %d\n", calc(10, 5));
calc = multiply;
printf("10 Ă— 5 = %d\n", calc(10, 5));
return 0;
}
Output:
10 + 5 = 15
10 - 5 = 5
10 Ă— 5 = 50
Same pointer, three different jobs! 🎉
📞 What is a Callback Function?
A callback is when you give your function to someone else, and THEY call it back later.
Real-Life Callback Story
Imagine ordering pizza:
- You call the pizza shop 📱
- You give them YOUR phone number
- You go play video games 🎮
- When pizza is ready, THEY call YOU back!
Your phone number is like a function pointer. The pizza shop (another function) uses it to “call you back” when it’s time.
Callback in Code
#include <stdio.h>
// This function will be "called back"
void ringDoorbell() {
printf("đź”” DING DONG! Pizza is here!\n");
}
// Pizza shop function accepts a callback
void pizzaShop(void (*notifyCustomer)()) {
printf("🍕 Making pizza...\n");
printf("🍕 Pizza is ready!\n");
// Call the customer back!
notifyCustomer();
}
int main() {
// Give pizzaShop our callback function
pizzaShop(ringDoorbell);
return 0;
}
Output:
🍕 Making pizza...
🍕 Pizza is ready!
đź”” DING DONG! Pizza is here!
🎨 Why Use Callbacks?
Callbacks let you customize behavior without changing the original function!
Example: A Flexible Printer
#include <stdio.h>
// Different ways to format a number
void printNormal(int n) {
printf("Number: %d\n", n);
}
void printFancy(int n) {
printf("✨ The number is: %d ✨\n", n);
}
void printLoud(int n) {
printf("!!! %d !!!\n", n);
}
// This function uses a callback
void processNumber(int n, void (*printer)(int)) {
printf("Processing...\n");
printer(n); // Call whatever printer was passed!
}
int main() {
processNumber(42, printNormal);
processNumber(42, printFancy);
processNumber(42, printLoud);
return 0;
}
Output:
Processing...
Number: 42
Processing...
✨ The number is: 42 ✨
Processing...
!!! 42 !!!
Same processNumber function, three different outputs!
🏗️ Real-World Use: Custom Sorting
One of the most famous uses of callbacks is sorting with custom rules!
#include <stdio.h>
#include <stdlib.h>
// Compare for ascending order
int ascending(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
// Compare for descending order
int descending(const void *a, const void *b) {
return (*(int*)b - *(int*)a);
}
int main() {
int numbers[] = {5, 2, 8, 1, 9};
int size = 5;
// Sort ascending using callback
qsort(numbers, size, sizeof(int), ascending);
printf("Ascending: ");
for(int i = 0; i < size; i++) {
printf("%d ", numbers[i]);
}
// Sort descending using callback
qsort(numbers, size, sizeof(int), descending);
printf("\nDescending: ");
for(int i = 0; i < size; i++) {
printf("%d ", numbers[i]);
}
return 0;
}
Output:
Ascending: 1 2 5 8 9
Descending: 9 8 5 2 1
The qsort function doesn’t know HOW to compare—you tell it through callbacks!
🗺️ Visual Flow: How Callbacks Work
graph TD A["Your Main Code"] -->|Passes function pointer| B["Library/System Function"] B -->|Does its work| C["..."] C -->|Calls YOUR function back| D["Your Callback Function"] D -->|Returns result| B B -->|Continues| E["Done!"]
🎓 Key Concepts Summary
| Concept | What It Is | Simple Example |
|---|---|---|
| Function Pointer | A variable holding a function’s address | int (*ptr)(int, int) = add; |
| Calling via Pointer | Using the pointer to run the function | ptr(5, 3); |
| Callback Function | A function you pass to another function | sort(array, myCompare); |
| Why Callbacks? | Customize behavior without changing code | Different sort orders |
⚡ Pro Tips
-
Parentheses matter!
int (*ptr)(int)→ pointer to functionint *ptr(int)→ function returning pointer (different!)
-
Function names ARE addresses
operation = add; // Works! operation = &add; // Also works! Same thing. -
Calling works both ways
operation(5, 3); // Works! (*operation)(5, 3); // Also works! Same thing.
🎉 You Did It!
You now understand:
- âś… Function pointers store function addresses
- âś… You can swap which function a pointer calls
- âś… Callbacks let you pass functions to other functions
- âś… This makes code flexible and reusable!
Function pointers = Magic remote controls for your code! 🪄
Next time you see callbacks in a library, you’ll know exactly what’s happening. The code is saying: “Hey, when I’m done with my job, I’ll call YOUR function back!”
