Tutorial Twelve – a look at function pointers

This is the twelfth tutorial in the series Online C Tutorials for beginners and is about pointer variables. These are single page bite size tutorials which can usually be run on either codepad.org or ideone.com.

What is a function pointer in C?

In these earlier tutorials, I’ve looked at pointers. Pointers are probably the single most important feature in C. These tutorials can remind you about them.

These have been about using pointers to data. But you can also use pointers to code, specifically functions.  To remind yourself about functions, there’s a look at functions.

Pointers at their simplest are just variables holding an address in RAM. If that address holds data then fine. If it holds code in the shape of a function then we can call it indirectly through the pointer. What makes pointers a little harder to understand is that with data we have to tell the C compiler what type of data the pointer is pointing to. This lets the compiler check for example that you aren’t assigning a float to a char pointer.

With pointers to functions, the compiler has to be given a function signature so the compiler can check that you aren’t calling a function pointer where the function has two int parameters and returns an int when the function pointer is pointing to a function that expect a char * to be passed in.

If it didn’t do this, you would get some weird and wonderful crashes. Most often when you call a function, the return address and parameters are pushed on the stack and then fetched by the function you’ve called. If the function called was different then it might pop off the wrong type of parameter, or the wrong number of parameters and might get a return address that was very wrong and could end up anywhere.  Not good.

Let’s start with the simplest of functions:

#include <stdio.h>

int add(int a, int b) {
	return a + b;
}

int main() {
	printf("a + b = %d\n",add(1,2));
	return 0;
}

Nothing unusual. It outputs a + b = 3 as you’d expect.

Now lets declare a function pointer which matches the add function.

int (*ptrAdd)(int, int);

This is not very intuitive, and probably the hardest part of C. This has declared a variable called ptrAdd which is a pointer to a function with two int parameters and which returns an int, i.e. exactly the same type of function as add.

Now because it is a variable, you have to put something in it. That something is a function.

You can do it in two ways which are the same. The & means address of so in (1) below you are storing the address of add in addPtr. (2) does the same because, a bit like arrays, the name of a function is also the address of that function. Ie the & in (1) is superfluous.

ptrAdd = &add;  // 1

ptrAdd = add;   // 2

So putting our program together we get this:

#include <stdio.h>

int add(int a, int b) {
	return a + b;
}

int (*ptrAdd)(int, int);

int main() {
	ptrAdd = add;
	printf("a + b = %d\n",ptrAdd(1,2));
	return 0;
}

This does exactly the same as the first program.  Try it on ideone.com.

That in a nutshell is what function pointers are all about. Wow you say, That’s it? Well that’s the mechanism. Their flexibility is that you can choose functions at runtime and pass them in and call them indirectly.  Let’s see an example of that.

#include <stdio.h>

int add(int a, int b) {
	return a + b;
}

int mult(int a, int b) {
	return a * b;
}

typedef int (*MyFunc)(int, int);

void callFunc(MyFunc f,int x,int y) {
	printf("Calling f = %d\n",f(x,y));
}

int main() {
	callFunc(add, 2, 3);
	callFunc(mult, 10, 2);
	return 0;
}

This outputs:

Calling f = 5
Calling f = 20

The typedef defines MyFunc as a type of function which passes in two ints and returns an int. I use MyFunc in the parameter list of callFunc. All it does is pass in the matching function name (add or mult) and two int parameters. It then calls that function f(x,y) and prints out the result. So 22 + 3 = 5 and 10 x 2 = 20.  Try this on ideone.com.

Being able to pass the function pointer around, just like any parameter is what makes it useful. So long as the function matches the parameters defined in the typedef you are ok. If you want to use functions with different parameter types or return types then you need to define more function pointers.

(Visited 26 times, 1 visits today)