This node concerns using and understanding arrays of function pointers in the C language. Other languages not included, 1/bazillion chance of winning, see official rules for details. I have generally checked the code herein using gcc (and had to correct it extensively); the code that is shown here should work if used right. (Note: Now corrected of my errant Casting the return value of malloc()) If you wish to see this done in a high level language (Python), scroll to the bottom, but it's completely trivial.

Crazy Pre-node-content Rambling

Function pointers are an essential part of the C language. Function pointers allow flow control in C to be dynamic in much the same way that malloc() and free() allow memory use to be dynamic. With function pointers, programmers can easily solve complex problems with code simplicity that is otherwise only generally possible in higher level languages. You need to learn how to use function pointers as data if you're going to be writing C.

Note that even in high level languages, function pointers are used at a low level to implement high level features such as polymorphism using abstract classes or interfaces. Different implementations of the same function are pointed to in a Virtual Method Table (VMT), incurring some overhead in calling. Here as everywhere, higher level languages like C++ and Java exchange very basic control for some extra readability and transparency of use. (Thanks to StrawberryFrog for the info, kick me if this is all wrong.)

Bjarne Stroustrup said, "An array of function pointers is a handy thing." He was right. We were assigned a project in my systems class that involved implementing a simple computer architecture which accepts eight instructions. Instead of using branching like everyone else, I wrote it in two lines of code and one array initialization.

Actual Node Content

If you aren't already familiar with function pointer, visit the function pointer node for some pointers. (I'll be here 'til Thursday. Try the veal.)

Using an array of function pointers is nearly as easy as plain function pointers or plain arrays, but the syntax can be a pain if you're not very thourough. If this educates you such that you can do this right the first or second time, without scrabbling around in arcane documentation, we can both call it a moral victory.

Remember that in order to use an array of function pointers, the functions you put in it must have the same return type an argument list. (Okay, so they don't have to if you twist C's arm, but that's dangerous and crazy.) If the functions you are using differ, there isn't much of a reason to have an array of pointers for them other than obfuscation; try using a struct instead.

Basic Syntax

The two basic ways you will see function pointer arrays are using array notation, and using pointer notation and a arithmetic. The basic syntax you can follow for declaring these is:

// Declare an array of function pointers
return_type (*array_identifier[array_size])(arg1 type_of_arg1, ...);

// Declare a pointer to a function pointers
// (To dynamically create an array)
return_type (**array_identifier)(arg1 type_of_arg1, ...);
This will get you an array of size array_size, or a null pointer if you're going to allocate it. The actual type of those monsters in allocation is just this bit:
// Type of 1 functions pointer (used with sizeof):
size_t s = sizeof( ( return_type (*)(arg1 type1,...) );

// Type of an array (used to cast an arbitrarily typed pointer)
some_array = ( return_type (**)(argument list...) ) some_pointer;
// Note: I changed this to being just an arbitrary cast of
// a variable because of Casting the return value of malloc().
// Previously it was a cast of a malloc call; I suppose you might
// still need this in C++, according to said node.
Lastly, in order to access these arrays ( which usually means calling a function ), you use something like this:
// Set second function pointer in array to function foo
// Note that foo needs to be a correctly typed function
fp_array[1] = foo;

// Same thing, using pointer notation
*(fp_array + 1) = foo;

// Calling the function we've just set, both ways

some_value = (fp_array[1])(arguments...);
some_value = (*(fp_array+1))(arguments...);

The Sort Of Easy Way

The easiest way to declare an array of function pointers is by using so many parentheses it can't possibly not work, and a constant number of elements. Example: Suppose you have three functions, foo, bar, and baz that take a singe integer argument and return void. (Note I don't bother with a complete program here. Place this code in a standard C program, along with functions foo, bar, and baz, to get actual results.)

void (*fooBarAndBaz[3])(int) =  {foo, bar, baz}; 
// Declare a 3 element array of function pointers;
void (*fooOrBarOrBaz)(int); 
// Declare a single function pointer

(fooBarAndBaz[0])(1); // Call foo sending int 0;
(fooBarAndBaz[1])(5); // call bar sending int 5;

(fooBarAndBaz[2])(100); // Call baz sending int 100;
fooOrBarOrBaz = fooBarAndBaz[1]; // This is the same (now) as
fooOrBarOrBaz = bar; // this;
// Both lines point the single function pointer fooOrBarOrBaz to the second
// element of the array of function pointers, with is the funtion bar.

fooOrBarOrBaz(50); // Call bar with value 50.
I hope it is clear what is going on here. The array of function pointers is fooAndBarAndBaz; I've placed the identifier in parentheses for cleanliness, and because function pointers act up pretty easily. Note that the array part comes right after the name of the identifier, just like any other array. Don't try to put this anywhere else. I've placed the functions in the array using curly bracket notation, just like with other arrays, and you access the elements of the arrays using square brackets and the index. The only difference is that when you use a function pointer, you are calling a function, instead of accessing a value.

The slightly harder way

A slightly more complicated way to use an array of function pointers is with dynamic sizing; I will demonstrate this side by side with a normal array, to reduce confusion.

void (**fooBarAndBaz)(int); 

/* The same as above array, but just as a pointer 
to a pointer, rather than making an array of pointers. */

int *someNumbers; 
/* The same thing, but for an array of integers, we 
just need a pointer to an integer to use it like an array. */

someNumbers = (int *) malloc( sizeof( int ) * 3 ); 
// Use malloc with the type in the array

fooBarAndBaz = malloc( sizeof( void (*)(int) ) * 3);
/* I didn't really need the explicit cast from malloc, but it helps
to show what is going on. */
I hope you see the parallel between the integer array and the function pointer array. Note that the grammar of function pointers gets more obscure when there's no identifier to help it on. You could follow this by adding foo, bar, and baz to the array and using them, just like above.

First class functions as function pointers, or vice versa (Example in Python)

Most high level languages, in the tradition of Lisp, have first-class functions as a primary tool. These languages usually have true closures, which C does not have.

Python is dynamically typed language with first class functions, and you can do just about anything on the fly without any hassle. It might be more Pythonic to do this with a set of classes, but then, it might not. Anyway, here is a rundown:



cheeses = {
 cheddar: "It's the most popular cheese in the world!", 
 winsleydale: "Not round these parts, sir."
}

def check_cheese(type = "rochester"):
 if cheeses.has_key(type):
  print cheeses[type].description
 else:
  print "Hey, what do you mean 'miss'?"

def dead_parrot(bird):
 print "This " + bird + " is no more! It has ceased to be!"

list = [check_cheese, dead_parrot, lambda x: print "I don't like " + x]
# Three item list

for gag in list:
 gag('spam')

Naturally, this code doesn't do anything useful, but it does show off the ease of function pointers in Python. I added this because I've been using Python recently and it's really fluffy.

Final comments

Understanding an array of function pointers is important, but function pointers can be used in all sorts of data structures, just like other data types. Imagine the usefulness of a linked list of function pointers, used for implementing callbacks for example, or a tree of function pointers and values used to hold an algebraic expression; the possibilities are nearly endless. Of course, there are all sorts of other ways to do these things, but function pointers provide a handy alternative to procedural or even class-based ways of solving problems.

The better part of my understanding of function pointers comes from C Unleashed. Thanks to various others.

Log in or register to write something here or to contact authors.