Previous Page
Next Page

9.5. Pointers to Functions

There are a variety of uses for function pointers in C. For example, when you call a function, you might want to pass it not only the data for it to process, but also pointers to subroutines that determine how it processes the data. We have just seen an example of this use: the standard function qsort( ), used in Example 9-4, takes a pointer to a comparison function as one of its arguments, in addition to the information about the array to be sorted. qsort( ) uses the pointer to call the specified function whenever it has to compare two array elements.

You can also store function pointers in arrays, and then call the functions using array index notation. For example, a keyboard driver might use a table of function pointers whose indices correspond to the key numbers. When the user presses a key, the program would jump to the corresponding function.

Like declarations of pointers to array types, function pointer declarations require parentheses. The examples that follow illustrate how to declare and use pointers to functions .

double (*funcPtr)(double, double);

This declaration defines a pointer to a function type with two parameters of type double and a return value of type double. The parentheses that enclose the asterisk and the identifier are important. Without them, the declaration double *funcPtr(double, double); would be the prototype of a function, not the definition of a pointer.

Wherever necessary, the name of a function is implicitly converted into a pointer to the function. Thus the following statements assign the address of the standard function pow( ) to the pointer funcPtr, and then call the function using that pointer:

double result;
funcPtr = pow;                  // Let funcPtr point to the function pow( ).
                                // The expression *funcPtr now yields the
                                // function pow( ).

result = (*funcPtr)( 1.5, 2.0 );  // Call the function referenced by
                                  // funcPtr.
result = funcPtr( 1.5, 2.0 );     // The same function call.

As the last line in this example shows, when you call a function using a pointer, you can omit the indirection operator, because the left operand of the function call operator (i.e., the parentheses enclosing the argument list) has the type "pointer to function" (see "Function Calls" in Chapter 5).

The simple program in Example 9-5 prompts the user to enter two numbers, then performs some simple calculations with them. The mathematical functions are called by pointers that are stored in the array funcTable.

Example 9-5. Simple use of function pointers
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

double Add( double x, double y ) { return x + y; }
double Sub( double x, double y ) { return x - y; }
double Mul( double x, double y ) { return x * y; }
double Div( double x, double y ) { return x / y; }

// Array of 5 pointers to functions that take two double parameters
// and return a double:
double (*funcTable[5])(double, double)
          = { Add, Sub, Mul, Div, pow }; // Initializer list.

// An array of pointers to strings for output:
char *msgTable[5] = { "Sum", "Difference", "Product", "Quotient", "Power" };

int main( )
{
  int i;                  // An index variable.
  double x = 0, y = 0;

  printf( "Enter two operands for some arithmetic:\n" );
  if ( scanf( "%lf %lf", &x, &y ) != 2 )
    printf( "Invalid input.\n" );

  for ( i = 0; i < 5; ++i )
    printf( "%10s: %6.2f\n", msgTable[i], funcTable[i](x, y) );

  return 0;
}

The expression funcTable[i](x,y) calls the function whose address is stored in the pointer funcTable[i]. The array name and subscript do not need to be enclosed in parentheses, because the function call operator ( ) and the subscript operator [ ] both have the highest precedence and left-to-right associativity (see Table 5-4).

Once again, complex types such as arrays of function pointers are easier to manage if you define simpler type names using typedef. For example, you could define the array funcTable as follows:

typedef double func_t( double, double );     // The functions' type is now
                                             // named func_t.
func_t *funcTable[5] = { Add, Sub, Mul, Div, pow };

This approach is certainly more readable than the array definition in Example 9-5.


Previous Page
Next Page