24.3 Function Pointers and Prototypes

It's generally a good idea to have a function prototype in scope whenever you call a function. Function prototypes allow the compiler to generate correct code for function calls, and to verify that you've called a function with the correct number and type of arguments. Standard library functions are prototyped by including the relevant standard header files, and it's generally recommended that you write prototype declarations for your own functions, too, usually placing those declarations in your own header files. But what prototype can be used for an indirect function call using a function pointer, such as

	(*pfi)(arg1, arg2)
In general, it won't be known until run time what function pfi actually points to, so there's no way for the compiler to check the call against the prototype of the actually-called function. (We may know that pfi points to f1, f2, or f3, and we may have supplied prototypes for those functions, but that's immaterial.)

We've seen that when you declare a function pointer, you must declare what the return value of the pointed-to function will be. It's also possible to specify what the prototype of the pointed-to function will be. Here's our earlier declaration of pfi, beefed up with a prototype for the arguments:

	int (*pfi)(int, int);
Now we know that pfi is a pointer to a function, that the function (whatever it is) accepts two int arguments, and that the function returns an int. Having specified this, the compiler will now be able to do some more checking for us. If we call
	(*pfi)(1, 2, 3)
the compiler will complain, because it knows that the function pointed to by pfi is supposed to receive two arguments, but we've passed three. The compiler is also in a position to verify that we actually set pfi to point to functions that accept two int arguments. Our examples so far were in terms of functions which we declared as
	extern int f1();
	extern int f2();
	extern int f3();
that is, as functions taking unspecified arguments and returning int. (Remember, empty parentheses in an external function declaration indicate that the function accepts unspecified arguments, while empty parentheses in a function definition indicate that the function accepts no arguments.) So the compiler won't be able to check the assignments unless we also provide prototypes:
	extern int f1(int, int);
	extern int f2(int, int);
	extern int f3(int, int);
Now, when we assign
	pfi = f1;
the compiler can verify that the function pointer being assigned is to a function which accepts two int arguments, as pfi expects. If, on the other hand, we declared and assigned
	extern int x(int);
	pfi = x;
the compiler would complain, because pfi is supposed to point to a function which accepts two int arguments, and the eventual call to (*pfi)() is going to be verified to be a call passing two arguments, so assigning pfi to point to x (which accepts a single argument) is incorrect.


Read sequentially: prev next up top

This page by Steve Summit // Copyright 1996-1999 // mail feedback