In C function names are not themselves variables, but you can define a pointer to a function (similarly to arrays). This allows you, for example, to invoke one of several functions from a single call, reassigning the function pointer in between. To see how this works, we first introduce the syntax needed to talk about these things.
We already have something similar:
int *int_ptr;
says that int_ptr is a pointer to an integer. It is not itself an integer, merely something which, when we follow it, we find an int.
Consider:
int (*f_ptr)();
This says that f_ptr is a pointer to a function (and that function returns an int).
f_ptr is not itself a function, but if we follow it we will find one.
[If it was a function, returning a pointer to an int, we would have written:
int *f_ptr()
If we had wanted a pointer to a function returning a pointer to an int, we would have written:
int *(*f_ptr)();]
As with array names, function names are in fact pointers to the function proper. Hence we can assign them to a function pointer. Suppose we have already got two int functions f1 and f2. We can now write:
f_ptr= f1;
If we now ``call'' f_ptr we will invoke f1: how do we do this? We write:
(*f_ptr)(argument_list)
As with other uses of pointers, we use the * to follow the pointer. The brackets are necessary to get the correct association (otherwise it will try to invoke f_ptr(argument_list) before applying the *). Of course we can subsequently write:
f_ptr= f2;
and then the same call will produce a different effect. This is a very useful mechanism allowing generality of code and also portability. Like all of C's generous features it can also be used to the opposite effect!
One example: you can write a general multiply which will work as well with matrices as with scalars, by rebinding the call according to the type of object.
Another example: you can write a set_pixel routine which works with any depth of pixel, even though the address calculation and bit masking operations are radically different for, say, 1 bit pixels compared with 8 or 32 bits.
Finally, it means you can pass functions as arguments.
ANSI C also allows you to write
f_ptr(argument_list)
just the same as an ordinary procedure call. My own preference is not to do this, simply because you normally use function pointers for some special reason and I think it is better to remind the reader that function pointers are in use with:
(*f_ptr)(argument_list)
maspjw@