Expert · Bits, undefined behaviour and safety · topic 45 of 60 · 30 min
Function pointers and callbacks
Explanation
Declaring and calling
int add(int a, int b) { return a + b; }
int mul(int a, int b) { return a * b; }
int (*op)(int, int); /* op is a pointer to a function taking (int, int) returning int */
op = add; /* a function name decays to its address (&add also works) */
printf("%d\n", op(3, 4)); /* 7 */
op = mul;
printf("%d\n", op(3, 4)); /* 12 */Dispatch tables
typedef double (*Calc)(double, double);
double c_add(double a, double b) { return a + b; }
double c_sub(double a, double b) { return a - b; }
double c_mul(double a, double b) { return a * b; }
Calc table[] = { c_add, c_sub, c_mul }; /* index = menu choice */
const char *names[] = { "add", "subtract", "multiply" };
int choice = 2;
if (choice >= 0 && choice < 3) printf("%s: %.1f\n", names[choice], table[choice](6, 7)); /* multiply: 42.0 */Callbacks: qsort
qsort (from <stdlib.h>) sorts any array. It does not know your element type, so you pass the element size and a comparison function. qsort calls your function with pointers to two elements; it must return a negative number, zero or a positive number.
#include <stdlib.h>
int compare_ints(const void *a, const void *b) {
int x = *(const int *) a;
int y = *(const int *) b;
return (x > y) - (x < y); /* -1, 0 or 1, without overflow */
}
typedef struct { char name[20]; int marks; } Student;
int by_marks_desc(const void *a, const void *b) {
const Student *s = a, *t = b;
return (t->marks > s->marks) - (t->marks < s->marks);
}
int nums[] = {42, 7, 19, 3};
qsort(nums, 4, sizeof nums[0], compare_ints); /* 3 7 19 42 */
qsort(students, n, sizeof students[0], by_marks_desc); /* topper first */Callbacks in your own code
typedef void (*OnAlert)(const char *msg);
void check_temperature(double t, OnAlert alert) {
if (t > 8.0) alert("Cold store above 8 °C");
}
void sms_alert(const char *m) { printf("SMS: %s\n", m); }
void log_alert(const char *m) { fprintf(stderr, "LOG: %s\n", m); }
check_temperature(9.5, sms_alert); /* the caller chooses what happens */Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Function pointers and callbacks · 1/6
In this lesson you will store functions in pointers and pass them around.
Prefer a video by a teacher? Find free videos on “c function pointers callbacks qsort comparator dispatch table” on YouTube ↗
In real life: Event handlers in firmware
A smart-lock firmware registers a handler function for each event: keypad code entered, fingerprint matched, battery low. The event loop looks up the handler in a table of function pointers and calls it, so new events need only a new function and a table entry.
typedef enum { EV_KEYPAD, EV_FINGERPRINT, EV_BATTERY_LOW, EV_COUNT } Event;
typedef void (*Handler)(void);
void on_keypad(void) { /* verify code, unlock */ }
void on_fingerprint(void) { /* unlock */ }
void on_battery_low(void) { /* beep three times */ }
static const Handler handlers[EV_COUNT] = { on_keypad, on_fingerprint, on_battery_low };
void dispatch(Event e) { if (e < EV_COUNT && handlers[e]) handlers[e](); }Practice (0/3 done)
What does this print? int sq(int x) { return x * x; } int neg(int x) { return -x; } int (*f[])(int) = { sq, neg }; printf("%d\n", f[1](f[0](3)));
In JavaScript, functions are values too, so the same callback idea runs here: write sortStudents(students) that returns a NEW array sorted by marks descending, then by name A–Z, using a comparator function that returns negative, zero or positive WITHOUT subtracting marks (use comparisons, like (a > b) - (a < b) in C).
Write a C calculator menu using a dispatch table of function pointers (add, subtract, multiply, divide with a divide-by-zero check), selected by the user's number. Then sort an array of struct Product { char name[20]; double price; } with qsort twice: by price ascending and by name, with correct comparators.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Undefined behaviourBits, undefined behaviour and safety · same module
- Masks and flagsBits, undefined behaviour and safety · same module
- Why async, and callbacksJavaScript Programming (language in depth) · Asynchronous JavaScript
- FunctionsFrontend Web Development · JavaScript basics
- Arrow functionsJavaScript Programming (language in depth) · Functions and closures
- Pointers and functionsPointers
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What does int *f(int) declare?
Answer: A function returning int *
Without brackets around *f, it is a function declaration.
What must a qsort comparator return?
Answer: Negative, zero or positive
Like strcmp.
Why avoid return a - b in comparators?
Answer: It can overflow and give the wrong sign
Use (a > b) - (a < b).
What is a callback?
Answer: A function passed to other code so that code can call it later
qsort's comparator is a callback.
Which copies array a (3 ints) into array b?Related
In an error-first callback (err, data), what should you do first?Related
What is a callback?Related
Answer: A function passed to another function to be called later
Callbacks are functions given to other functions, for example to run on each item or on a click.
From Functions
Where does an array NOT decay to a pointer?Related
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- This is the last topic of “Bits, undefined behaviour and safety”. The module exam comes next.
- Module 9 exam: Bits, undefined behaviour and safety · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Data structures in C. 60 topics left in the course before the final exam.