Previous Table of Contents Next


Pointers to functions are used analogously to pointers to data objects. Function pointer variables must first be initialized, typically with pointer values built as if by applying the & operator to the names of actual functions. For example, we might write something like

extern int f1(float, float);
int (*funcptr)(float, float);
funcptr = &f1;

Now funcptr points to the function f1(). However, in this case, the explicit & operator is optional and is usually omitted:

extern int f2(float, float);
funcptr = f2;

The syntax is unambiguous: Because the appearance of f2 in the assignment is not followed by a parenthesized argument list, it does not represent a call to f2, and there is, in fact, no other interpretation than that a pointer to f2 is required. (In other words, the rule for function names that appear in expressions where they are not being called is similar to the rule for array names in expressions where they are not being subscripted. In both cases, pointers are implicitly generated.)

Given a pointer to a function, the obvious thing to do is to call the function pointed to. Reasoning by analogy with pointers to data objects, you might attempt to use the * operator to “take the contents of” the function pointer, resulting in an actual function that could then be called. In fact, such a syntax does work, although an extra set of parentheses is again required to get the precedence right:

int n = (*funcptr)(f1, f2);

Without the parentheses, the call would be *funcptr(f1, f2), which would attempt to call the function named funcptr and then take the contents of the pointer value returned, which would make sense in this case only if funcptr were a function returning pointer to int, which it is not.

However, here again a simplification is possible, and is often seen in modern code. If funcptr is a pointer to a function, there are only a few things that can be done with it: assign or compare it to some other function pointer, or call the function it points to. Therefore, the calling syntax

n = funcptr(f3, f4);

without the explicit * and parentheses, is unambiguous, and is also legal. A programmer using a lot of function pointers (as in object-oriented programming) may prefer the convenience of omitting the extra syntax, but when function pointers are a rarity in a piece of code, you might prefer to call attention to their exceptional use by using the exceptional-looking, explicit syntax.

Given the existence of function pointer values and variables to hold them, it is possible, naturally enough, to define functions that accept function pointers as parameters. The traditional example is a sorting function. Suppose we have a function

int asort(int a[], int n);

which sorts n elements in the array a. Suppose further that there are several different ordering relations under which the array might be sorted (perhaps normal, reverse, and odd-followed-by-even). We can define several comparison functions, each of which compares two integers and returns a result indicating whether one of the two integers should be considered greater, equal, or less than the other for the purposes of the sort. Then we modify the asort function to accept the comparison function as a third parameter:

int asort(int a[], int n, int (*cmpfunc)(int, int));

As it does its work, the new version of asort calls (*cmpfunc)(a[i], a[j]) to determine the desired relative position of two array elements a[i] and a[j]. Supposing that our several comparison functions were declared as

int cf1(int, int), cf2(int, int), cf3(int, int);

we could call any of

asort(a, n, cf1);
asort(a, n, cf2);
asort(a, n, cf3);

depending on the desired ordering. The standard C library defines a function that can sort arrays of any type (not just int) according to a caller-supplied comparison function; see section 3.10.4.4.


Previous Table of Contents Next