Step 1 of 6
Functions have addresses
Functions live in memory too. The compiled machine code of a function sits at some address, and just as you can store the address of an int in a pointer, you can store the address of a function in a function pointer and call the function through it later. This lets a program choose which function to run while it's running, and it's the foundation of callbacks, plugins and dispatch tables.
#include <stdio.h>
double half(double x) { return x / 2; }
double twice(double x) { return x * 2; }
int main(void) {
double (*f)(double) = half;
printf("%.1f\n", f(9));
f = twice;
printf("%.1f\n", f(9));
double (*pick[2])(double) = {half, twice};
printf("%.1f\n", pick[1](pick[0](10)));
return 0;
}
4.5
18.0
10.0
Reading the declaration
double (*f)(double) reads from the name outward: f is a pointer (*f, in parentheses) to a function taking a double ((double)) and returning a double. The parentheses around *f are essential. Without them, double *f(double) declares a function named f that returns a double *.
Using them
- A function's name used without calling it (
half, nothalf()) gives its address. You can also write½ it means the same. - Call through the pointer exactly like a normal function:
f(9). (The old style(*f)(9)also works.) - The pointer's type must match the function's signature: parameter types and return type.
pickis an array of function pointers, which is the basis of the dispatch tables coming up in step 3.
Your turn: point op at sub and call it.