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 task
Point op at sub and call it.
Challenge 2
An array can hold function pointers too. Fill the table with add and mul, so the loop prints 7 and then 12.
Challenge 3
Write int twice(int (*f)(int), int x) that applies f to x two times, f(f(x)). With the functions below, the program prints 7 (5 plus 1, plus 1) and 81 (3 squared, squared).