Function Pointers, the MacGyver of C
08 Dec 2012Introduction
It’s a very well studied topic in the C field. Many people have written tutorials on how to use function pointers and what they are. The function pointer tutorial is always a good read for the uninitiated or seasoned professional who’s function pointer theory is a little rusty.
This write up isn’t going to try and fill the shoes of the basic-square-1-hello-world style tutorial. I just wanted to talk about how I’ve used them to better a piece of code and make a system a bit more extensible overall.
What are they?
Like any data pointer a function pointer is an address. It’s an address that will point to the entry-point of some code. It’s that simple. The complexity comes into the argument when you start to add C syntax. C likes to be very descriptive with the data that you’re feeding functions and function parameters are no exception.
Ok, simple example time over. It’s onto what this article is really about.
Problem description
I have a game that has a few game states. They look like this:
- Introduction credits
- Game title
- Menu
- Game play
- Game over
- High score board
Each of these states all have functionality that they need to accomplish. The basic specification for a game state goes as follows:
- Needs to be able to be initialized
- Needs to be able to have its resources freed (tear down)
- Needs to be able to update its internal logic
- Needs to be able to render its internal state
- Needs to be able to respond to events (keyboard, etc)
Good. We’ve established that we have a set of game states and they all attract a set of actions that we’d like them to perform.
Getting down to it
So, let’s define the actions first (as function pointers) and we can then fill in the implementation later:
Slightly different from above is the use of the “typedef” keyword. This allows us to define these function pointers as types so that we can treat them just as we do any other type. These types that we’ve defined are the outline to what we need. We still have the colour in, but we’ve got a framework ready to go. Lets define our function pointer variables using the types we defined above.
Simple enough. Now that we have these variables define (close-by to our game loop), we can write a game loop that will look a little something like this:
This is psuedo code really. There’s a whole heap of infrastructure that you’ll need in order to make this work. You can see that only 3 of the functions we require are being are being used at the moment. We still need to get the init and teardown involved. The game module also needs a way to shift between game states. Thankfully, both of these functions come together in the one function:
So, this function tearsdown the existing game state (if we have a state), and initializes if we initialize to a valid state. Easy!! Well, this has been just one possible use for function pointers. You can do so much, much more with them, but I thought I’d share my use of them here!