Dispatch tables can be implemented in several ways. One is with a table of pointers to functions:
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 a / b; }
int DoFunction(int Select, int a, int b)
{
/* Declare a type to point to a function with parameters (int a, int b)
and returning an int.
*/
typedef int (*MyFunctionPointer)(int a, int b);
// Build a dispatch table with pointers to functions.
MyFunctionPointer Table[] =
{
Add,
Subtract,
Multiply,
Divide,
};
// Dispatch to the requested function.
return Table[Select](a, b);
}
#include <stdio.h>
int main(void)
{
// Demonstrate calls using dispatch table.
printf("7 + 3 = %d.\n", DoFunction(0, 7, 3));
printf("7 - 3 = %d.\n", DoFunction(1, 7, 3));
printf("7 * 3 = %d.\n", DoFunction(2, 7, 3));
printf("7 / 3 = %d.\n", DoFunction(3, 7, 3));
}
One might also jump into a table of branch instructions. This is more common in assembly than in higher level languages.
Essentially, a dispatch table is some method of transferring program control to a location selected via an index, rather than by individual selections such as with if
or switch
statements. In some situations, it is easier or cleaner to compute an index to select a function than to write some convoluted selection statements.
(This example shows homogeneous functions—they all have the same parameter type list and return type. If functions are not homogeneous, it may be trickier to use a dispatch table in C.)
Although dispatch tables are not frequently encountered in much source code (nor are they uncommon), they can be used for a variety of things, such as:
On some processors, interrupt service routines are handled through a dispatch table: There are fixed locations in memory where addresses of routines are stored, forming a table of addresses. When an interrupt occurs, the hardware looks up the address and transfer control to it.
In code that should be high-performance on a variety of hardware, we might prepare several functions that each use a different algorithm designed for particular hardware. When the program starts, it could test what hardware it is executing on (such as specific processor model) and record an index into the table. That index would indicate which routine to execute. Then calls to the function can use the index table for quick dispatching, without needing to test-and-branch for each call.