Game programming/Function pointers
< Game programmingIn C, pointers are everywhere. You are probably familiar with pointers to variables. Maybe even pointers to structs. A pointer is a variable which holds a memory address. It usually has some useful value, like a acting as a reference to a variable in a different scope. In C, you can also have pointers to functions.
Requirements
- C knowledge
Objectives
- To know how to make a pointer to a function
- To know how to use a pointer to a function
- To get to know some usage examples of pointers to functions
Introduction
First, let's look at a function declaration.
double getAvg(double a, double b)
{
return (a + b) / 2;
}
As you can see, we have here a function called "getAvg". It receives two doubles and returns a double.
Explanation
A pointer to a function does looks mostly not different from a regular function, except it has the '*' symbol as in all pointers, and parenthesis as follows:
/* Declaration */
double (*fp(double, double));
/* Assignment */
fp = &getAvg;
/* Use */
fp(2, 3);
Here we have a pointer called "fp", so we'll refer to it as such. It is a pointer to a function that receives two doubles and returns a double.
Note how we do not add the parenthesis after getAvg when we assign it's address to fp. Also note the '&' operator.
Using a pointer to a function is not different from using a normal function. Hence, we could do the following:
printf("fp(2, 3) = %f.2\n", fp(2, 3));
Application
Pointers to functions serve three general purposes. One is that they provide a way to have methods in structs, the second is that they allow for some degree of polymorphism, and the third is passing functions to functions.
To create methods in a struct,
#include <stdio.h>
typedef struct
{
double a;
double b;
double (*getAvg)(MyStruct_t*);
} MyStruct_t;
double _MyStruct_t_getAvg(MyStruct_t* this)
{
return (this->a + this->b) / 2;
}
MyStruct_t* createMyStruct(double da, double db)
{
MyStruct_t* new = (MyStruct_t*) malloc(sizeof(MyStruct_t));
new->a = da;
new->b = db;
new->getAvg = &_MyStruct_t_getAvg;
return new;
}
int main(int argc, char* argv[])
{
MyStruct_t* strct = createMyStruct(2, 3);
printf("getAvg() = %f.2", strct->getAvg(strct));
return 0;
}
Note: This example isn't that useful. It requires work.
As an example of polymorphism,
#include <stdio.h>
void doOne(void)
{
printf("I've done One\n");
}
void doTwo(void)
{
printf("I've done Two\n");
}
void doNothing(void)
{
printf("I've done nothing\n");
}
int main(int argc, char* argv[])
{
void (*work)(void) = doNothing;
int state;
for(state = 0; state < 2; ++state)
{
if(state == 0)
{
work = &doOne;
}
else if(state == 1)
{
work = &doTwo;
}
else
{
work = &doNothing;
}
printf("State %d,\n", state);
work();
}
printf("Last work:\n");
work();
return 0;
}
And an example of sending functions through functions,
#include <stdio.h>
void doWork(void (*beforeBegin)(void), void (*afterDone)(void))
{
beforeBegin();
printf("I've done some work.\n");
afterDone();
}
void logBegin(void)
{
printf("LOG: I'm about to do some work.\n");
}
void logEnd(void)
{
printf("LOG: I'm done doing some work.\n");
}
int main(int argc, char* argv[])
{
doWork(logBegin, logEnd);
return 0;
}