
Replacing conditionals with function pointers
Previously, we looked at memory segments, and one of the most important segments is the code segment (also called a text segment). This segment contains the program image, which is the instructions of the program that should be executed. Instructions are usually grouped into functions, which provide a unique name allowing us to call them from other functions. Functions reside in the code segment of the executable file.
A function has its address. We can declare a pointer that takes the address of the function and then use it later to call that function:
int get_answer() { return 42; }
int (*fp)() = &get_answer;
// int (*fp)() = get_answer; same as &get_answer
The function pointer can be called the same way as the original function:
get_answer(); // returns 42
fp(); // returns 42
Let's suppose we are writing a program that takes two numbers and a character from the input and executes an arithmetic operation on the numbers. The operation is specified by the character, whether it's +, -, *, or /. We implement four functions, add(), subtract(), multiply(), and divide(), and call one of them based on the value of the character input.
Instead of checking the value of the character in a bunch of if statements or a switch statement, we will map the type of the operation to the specified function using a hash table:
#include <unordered_map>
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 divide(int a, int b) { return (b == 0) ? 0 : a / b; }
int main() {
std::unordered_map<char, int (*)(int, int)> operations;
operations['+'] = &add;
operations['-'] = &subtract;
operations['*'] = &multiply;
operations['/'] = ÷
// read the input
char op;
int num1, num2;
std::cin >> num1 >> num2 >> op;
// perform the operation, as follows
operations[op](num1, num2);
}
As you can see, std::unordered_map maps char to a function pointer defined as (*)(int, int). That is, it can point to any function that takes two integers and returns an integer.
Now we don't need to write the following:
if (op == '+') {
add(num1, num2);
} else if (op == '-') {
subtract(num1, num2);
} else if (op == '*') {
...
Instead, we simply call the function mapped by the character:
operations[op](num1, num2);