C Language | Advanced Features | Function Pointers
Functions have addresses. By storing a function address in a pointer, a program can choose which function to call at runtime.
Storing a Function Address
A function pointer is declared with the return type, pointer name, and parameter types.
return-type (*identifier)(parameter-type-list)
For example, int (*pf)(const char *) is a pointer to a function that receives a string and returns an int. Parentheses matter: int *pf(const char *) instead declares a function that returns an int *.
Given this function:
int Function(int , void *);
store its address as follows:
int (*pf)(int , void *) = Function;
Call the function through the pointer with either syntax:
i = pf(iValue , pointer);
i = (*pf)(iValue , pointer);
Code 1
#include <stdio.h>
void f(void) {
printf("Kitty on your lap\n");
}
int main() {
void (*fp)(void) = f;
fp();
(*fp)();
return 0;
}
Function pointers are useful for callbacks. A program can register a function with a system and let the system call it when an event occurs. They can also support extensible designs by storing multiple handlers in an array.
Registering Callback Functions
The following example adds and removes callbacks from a registry.
Code 2
#include <stdio.h>
#define ADD_FUNC 2
#define REMOVE_FUNC 4
#define RESULT_OK 0
#define RESULT_ERROR 1
typedef void(*REGISTERPROC)(const char * , int);
int RegisterFunc(REGISTERPROC func , int mode) {
static int iLen = 0;
static REGISTERPROC procs[256];
int iCount;
char removed;
switch(mode) {
case ADD_FUNC:
if (iLen == 256) return RESULT_ERROR;
for(iCount = 0 ; iCount < iLen ; iCount++)
if (procs[iCount] == func) return RESULT_ERROR;
procs[iLen++] = func;
for(iCount = 0 ; iCount < iLen ; iCount++)
procs[iCount]("Add" , iCount);
break;
case REMOVE_FUNC:
removed = 0;
for(iCount = 0 ; iCount < iLen ; iCount++) {
if (procs[iCount] == func) {
for(; iCount < iLen - 1 ; iCount++)
procs[iCount] = procs[iCount + 1];
iLen--;
for(iCount = 0 ; iCount < iLen ; iCount++)
procs[iCount]("Remove" , iCount);
removed = 1;
break;
}
}
if (!removed) return RESULT_ERROR;
break;
default:
return RESULT_ERROR;
}
return RESULT_OK;
}
void Function1(const char *msg , int value) { printf("Function1 : %s , %d\n" , msg , value); }
void Function2(const char *msg , int value) { printf("Function2 : %s , %d\n" , msg , value); }
void Function3(const char *msg , int value) { printf("Function3 : %s , %d\n" , msg , value); }
int main() {
RegisterFunc(Function1 , ADD_FUNC);
RegisterFunc(Function2 , ADD_FUNC);
RegisterFunc(Function3 , ADD_FUNC);
RegisterFunc(Function2 , REMOVE_FUNC);
RegisterFunc(Function3 , REMOVE_FUNC);
return 0;
}
REGISTERPROC is an alias for the callback pointer type. The registry accepts up to 256 callbacks, prevents duplicates, and notifies the remaining callbacks whenever an entry is added or removed.