Function Pointers in C

A function is not really a separate, isolated block of code so much as it is the address of the entry point to a series of instructions that are organized logically as a function. At the level of assembly language, a function is simply a sequence of instructions with a known starting point, which is the memory address of the first instruction.

#include <stdio.h>
#include <stdlib.h>

int addThree(int a, int b, int c);
int subThree(int a, int b, int c);

int main()
{
 printf("Location of addThree() function %p\n", addThree);
 printf("Location of subThree() function %p\n", subThree);

 return 0;
}


int addThree(int a, int b, int c) {
 return a + b + c;
}

int subThree(int a, int b, int c) {
 return a - b - c;
}

A function pointer is therefore nothing more than a pointer that stores the entry point address of a function.

When declaring a function pointer, we should take care to separate the pointer declaration from the type of the return value by enclosing the pointer declaration in a set of parentheses.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//same param list and return values

//returns long long
long long addNum(int x, int y) { return x + y; }
long long subtractNum(int x, int y) { return x - y; }

//returns double
double divideNum(int x, int y) { return (double)x / y; }
double multiplyNum(int x, int y) { return (double)x * y; }


int main()
{
 long long (*iAction)(int x, int y);
 double(*dAction)(int x, int y);
 
 iAction = addNum;
 dAction = divideNum;

 //dereference the function pointer to call the function
 printf("%lld\n", (*addNum)(1138, 1701));
 printf("%f\n", (*dAction)(47, 7));

 dAction = multiplyNum;

 printf("%lld\n", (*subtractNum)(1138, 1701));
 printf("%f\n", (*dAction)(100, 11));

 return 0;
}

Note that function names function in the same as array names, in that they both devolve to a memory address.

We can use function pointers to increase the flexibility of the flow of our program. For example, by using function pointers we can alter the order in which we call functions depending on either compile time or run time data.

#include <stdio.h>
#include <stdlib.h>

const int Num_Functions = 4;

void funcOne(void) {
 printf("Executing function one.\n");
}

void funcTwo(void) {
 printf("Executing function two.\n");
}

void funcThree(void) {
 printf("Executing function three.\n");
}

void funcFour(void) {
 printf("Executing function four.\n");
}

void(*funcArray[Num_Functions])(void) { funcOne, funcTwo, funcThree, funcFour };

int main()
{
 int i = 0;

 while (i < Num_Functions) {
 //using pointer arithmetic
 (*(funcArray + i++))();
 }

 printf("Now backwards!\n");

 //remember i is at 4
 //so we must decrement it before using it
 //as an index value
 while (i-- > 0) {
 //using indexers
 (*funcArray[i])();
 }
 return 0;
}

Another interesting thing we can do with function pointers is create a function dispatcher.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//note we are including time.h for the srand() function


const int Num_Functions = 4;

void functionW(const char *szArg) {
 printf("Function W acting on parameter '%s'\n\n", szArg);
}

void functionX(const char *szArg) {
 printf("Function X acting on parameter '%s'\n\n", szArg);
}

void functionY(const char *szArg) {
 printf("Function Y acting on parameter '%s'\n\n", szArg);
}

void functionZ(const char *szArg) {
 printf("Function Z acting on parameter '%s'\n\n", szArg);
}


void(*actions[Num_Functions])(const char *szArg) = { functionW, functionX, functionY, functionZ };

//this function calls the other functions we have defined. 
void dispatchFunction(int iType, char * szInstruction) {
 if ((iType > -1) && (iType < Num_Functions)) {
 (*actions[iType])(szInstruction);
 }
}

int main()
{
 const int num_arguments = 6;
 srand(time(NULL));
 

 char *szArgs[num_arguments] = { 
 "Nice boat!", 
 "That is mahogany!", 
 "Don't Panic",
 "Greetings, Professor Falken",
 "You are likely to be eaten by a grue.",
 "El Psy Congroo."
 };

 for (int i = 0; i < num_arguments; i++) {
 dispatchFunction(rand() % Num_Functions, szArgs[i]);
 }
 return 0;
}
Advertisements

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