Pass functions as data. Essential for qsort, callbacks, and dispatch tables.
typedef to name the typeqsort is enough for most jobsint (*fp)(int) β "fp is a pointer to a function taking int, returning int."
#include <stdio.h> int square(int x) { return x * x; } int main(void) { // fp points to "a function taking int, returning int" int (*fp)(int) = square; // function name decays to its address printf("%d\n", fp(5)); // 25 printf("%d\n", (*fp)(5)); // 25, older style return 0; }
fp = square and fp = &square are equivalent, as are fp(5) and (*fp)(5).fp(*fp) β fp is a pointer(int, int) β to a function that takes two intsint β returning intint *fp(int); // β NOT a function pointer // it's the prototype of a function returning int* int (*fp)(int); // β function pointer
typedef int (*CmpFn)(const void *, const void *); void sort(int *a, int n, CmpFn cmp) { /* ... */ }
CmpFn is defined, CmpFn x; declares a function pointer.#include <stdio.h> void for_each(int *a, int n, void (*fn)(int)) { for (int i = 0; i < n; i++) fn(a[i]); } void print_int(int v) { printf("%d ", v); } void print_square(int v) { printf("%d ", v * v); } int main(void) { int a[] = {1, 2, 3, 4, 5}; for_each(a, 5, print_int); printf("\n"); for_each(a, 5, print_square); printf("\n"); return 0; }
qsort takes a comparison function as a function pointer, so it can sort any type β ints, strings, structs.void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
#include <stdio.h> #include <stdlib.h> int cmp_int_asc(const void *p1, const void *p2) { int a = *(const int *)p1; int b = *(const int *)p2; if (a < b) return -1; if (a > b) return 1; return 0; } int main(void) { int a[] = {5, 2, 8, 1, 9, 3}; qsort(a, 6, sizeof(int), cmp_int_asc); for (int i = 0; i < 6; i++) printf("%d ", a[i]); // 1 2 3 5 8 9 }
return a - b; seems to work but overflows for large or negative values. Always compare and return -1 / 0 / 1.struct Student { char name[32]; int score; }; // higher score first, ties broken by name int cmp_student(const void *p1, const void *p2) { const struct Student *a = p1; const struct Student *b = p2; if (a->score != b->score) return (b->score > a->score) ? 1 : -1; return strcmp(a->name, b->name); } qsort(students, n, sizeof(struct Student), cmp_student);
switch for clean, data-driven code:#include <stdio.h> double op_add(double a, double b) { return a + b; } double op_sub(double a, double b) { return a - b; } double op_mul(double a, double b) { return a * b; } double op_div(double a, double b) { return b != 0 ? a / b : 0; } struct OpEntry { char sym; double (*fn)(double, double); }; static const struct OpEntry ops[] = { {'+', op_add}, {'-', op_sub}, {'*', op_mul}, {'/', op_div}, }; double calc(char op, double a, double b) { for (int i = 0; i < sizeof(ops) / sizeof(ops[0]); i++) { if (ops[i].sym == op) return ops[i].fn(a, b); } return 0; } int main(void) { printf("%.2f\n", calc('+', 3, 4)); printf("%.2f\n", calc('*', 6, 7)); }
char *words[] = {"banana","apple","cherry"}; alphabetically. Note the comparator takes const char **.int filter(int *a, int n, int *out, int (*pred)(int)). Copy elements for which pred returns non-zero. Test with an even-number predicate.