Every C function has a name so you can easily call any function provided you know its name. However, every function also has identity (a memory address), thus you can also call any function provided you know its address. This is useful as it allows you to pass functions to other functions. This might seem odd since any function can invoke any other function by its given name, however the point of passing functions to functions is that different callers can pass different functions.
For example, consider the following implementation of the insertion sort algorithm:
void insertion_sort (int* arr, size_t size) {
// insertion sort... size_t gap;
int val;
for (size_t idx=1; idx<size; ++idx) {
gap = idx;
val = arr[gap];
while (0<gap && val<arr[gap-1]) {
arr[gap] = arr[gap-1];
--gap;
}
arr[gap] = val;
}
}
Note the comparison operation within the while loop (val<arr[gap-1]) means that this function will always sort the array in ascending order of value. We could include a bool flag in the arguments to be able to choose between ascending and descending order, but this makes our code less than efficient because we now have to repeatedly test the argument in the inner while loop:
void insertion_sort (int* arr, size_t size, bool ascend=true) {
// insertion sort... size_t gap;
int val;
for (size_t idx=1; idx<size; ++idx) {
gap = idx;
val = arr[gap];
while (0<gap && (ascend ? val<arr[gap-1]:val>arr[gap-1])) { <-- INEFFICIENT!
arr[gap] = arr[gap-1];
--gap;
}
arr[gap] = val;
}
}
A better approach is to pass the comparison operator itself. This is achieved by declaring the operator as a function:
bool less_than (int a, int b) { return a<b; }
bool greater_than (int a, int b) {return a>b; }
Note that both functions have the same prototype, they only differ by name. That is, they both accept two integer arguments and they both return a bool. Functions that return a bool are commonly known as predicates.
To create a function pointer we use the following declaration:
bool (*FuncPtr)(int, int);
This declares a function pointer named *FuncPtr that can refer to any function that accepts two integers and returns a bool. Note the function pointer name includes the asterisk. Note also that the parenthesis are required. Without them, the asterisk would bind to the return type instead of the function pointer:
bool *FuncPtr (int, int);
In other Words we end up declaring a function named FuncPtr that returns a pointer to bool, which is clearly not what we intended.
We typically use a typedef to avoid the (ugly!) syntax associated with function pointers:
typedef bool (*FuncPtr)(int, int);
Now we have a proper type name (FuncPtr) that we can use in our declarations.
We can now change our sorting function to accept and call the predicate:
void sort (int* arr, size_t size, FuncPtr pred) {
// insertion sort...
size_t gap;
int val;
for (size_t idx=1; idx<size; ++idx) {
gap = idx;
val = arr[gap];
while (0<gap && pred(val, arr[gap-1]) {
arr[gap] = arr[gap-1];
--gap;
}
arr[gap] = val;
}
}
The sorting algorithm can now be invoked as follows:
void f (int* arr, size_t size, bool ascend=true) {
if (ascend) {
sort (arr, size, less_than); // sorts the array in ascending order
} else {
sort (arr, size, greater_than); // sorts the array in descending order
}
}
Or more concisely:
void f (int* arr, size_t size, bool ascend=true) {
sort (arr, size, ascend ? less_than : greater_than);
}
Note that the bool flag is now tested outside of the algorithm and is therefore tested once per call, rather than multiple times within the algorithm itself.
Copyright © 2026 eLLeNow.com All Rights Reserved.