Function pointers in C

I cut my programming teeth on Java, and I have a deep appreciation for principles of object-oriented design. One of my projects as a graduate student, however, has given me the opportunity to do a lot of coding in C. I now have a deep appreciation for the performance that C offers over Java, C++, Perl, etc, and the understanding that comes from implementing data structures from scratch. One thing that initially intimidated me about C is that, unlike Java and C++, there is no built-in syntax for object-orientation. However, after seeing some good examples, I realized that object-orientation is a principle and not a language construct, and I’ve had no problems implementing these principles in my C code.

The biggest lessons I’ve had to learn with C have to do with memory management. Java hides this all from the programmer, but with C, the programmer is responsible to free every piece of memory he allocates. One concept I’ve found very useful in this regard is the C language function pointer construct. A function pointer is a variable whose value can be changed–it can refer to different functions at different stages of program execution. This is extremely useful in a variety of cases, but I primarily use it when writing destructors for my data structures. A generalized data structure like a linked list or a hash map is agnostic to the type of data it contains. That means when it’s time to free the memory occupied by the data structure, the data structure itself doesn’t know how to free the memory occupied by each element it contains. Hard-coding a particular free function would severely limit the usefulness of the data structure.

Enter function pointers. With function pointers, my data structures do not need to know which function to call to free all of the associated memory–they simply make a call to the function pointer, which the programmer has pointed at the correct free function to call at that moment.

Syntax

The syntax of a C function pointer is pretty simple.

return_value_type (*function_pointer)(arg1_type, arg2_type, ..., argn_type);

For example, if you wanted to define a function pointer that accepts 3 integers as arguments and returns a float, you would define it like so.

float (*my_fp)(int, int, int);

Now at this point, you can use the my_fp variable to call any function that takes 3 ints and returns a float. For example, if you have two compatible functions defined like this…

float mean(int a, int b, int c)
{
  return (a + b + c) / 3.0;
}

float transform(int a, int b, int c)
{
  int sum = a + b + c;
  return (a + c - log(b)) / log(sum);
}

…then you can assign the function pointer to call either of them and invoke those functions through the function pointer, like so.

my_fp = &mean;
float first = my_fp(1, 3, 9);

my_fp = &transform;
float second = my_fp(1, 3, 9);

printf("first: %.4f, second: %.4f\n", first, second);
// the output would be "first: 4.3333, second: 3.4704"

In action

The example above is pretty silly and trivial, so I also wanted to show how I am actually using function pointers in my code. Below is the destructor function for a hash map class I recently wrote. The first argument to the destructor function is a pointer to the hash map data structure itself, and the second argument is a function pointer to be used for freeing memory occupied by all of the objects contained in the hash map.

void hashmap_delete(Hashmap *hash, void (*valuefreefunc)(void *))
{
  HashmapItem *item, *temp;
  int i;

  if(hash == NULL)
    return;

  // Iterate through the hash table
  for(i = 0; i < hash->size; i++)
  {
    item = hash->table[i];
    while(item != NULL)
    {
      temp = item;                  // Each item in the hash table is a key/value pair. The keys are all char arrays, so we can 
      item = item->next;            // simply call "free" to release that memory. However, the hash map doesn't know what data 
      free(temp->key);              // type the values are, so it calls the function pointer. It is therefore the programmer's 
      if(valuefreefunc != NULL)     // job to make sure that the function pointer is pointing to the appropriate free function 
        valuefreefunc(temp->value); // for hash maps containing objects of a particular data type.
      free(temp);
    }
  }

  free(hash->table);
  free(hash);
}
Advertisements

One comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s