Function Pointers in C

A function pointer is a pointer that holds the address of a function, thereby giving our programs greater flexibility. This flexibility might (or might not, depending) come at the cost of increased use of system resources. 

The simplest function pointer we can have is a pointer to a function that accepts no parameters and doesn’t return a value. Such a pointer would look like void (*func)(); – we note here that the function pointer’s identifier, func, is preceded by an asterisk and enclosed in parentheses. 

Let’s look at an example.

#include <stdio.h>

void functionOne(void);
void functionTwo(void);

int main(void){

void (*funcA)();
void (*funcB)();

funcA = functionOne;
funcB = functionTwo;

funcA();
funcB();

return 0;

}

void functionOne(void){
printf("Function One called.\n");
}

void functionTwo(void){
printf("Function Two called.\n");
}

Assigning the function addresses to a function pointer is easy, just use the assignment operator use the function name as the rvalue. There’s no need to place the address-of operator before the function name. Just as with array names, the function name by itself returns the function’s address in memory. 

#include <stdio.h>

void printInt(int n);
void addDoubles(double dX, double dY);
int factorial(int n);

int main(void){

void (*funcOne)(int);
void (*funcTwo)(double, double);
int (*funcThree)(int);


funcOne = printInt;
funcTwo = addDoubles;
funcThree = factorial;

funcOne(73);
funcTwo(68.803, 18.0025);
printf("4! = %d\n", funcThree(4));

return 0;

}

void printInt(int n){
printf("Function received the integer %d\n", n);
}

void addDoubles(double dX, double dY){
printf("%f + %f = %f\n", dX, dY, dX + dY);
}

int factorial(int n){
int total = 1;
while(n>1){
total *= n--;
}
return total;
}

Passing a function as an argument to another function is not difficult. We must simply define a function pointer declaration as the parameter in the target function’s definition.

#include <stdio.h>

int divide(int x, int y);
int subtract(int x, int y);
int add(int x, int y);
void compute(int x, int y, int (*operation(int,int)));


int main(void){

int (*func)(int, int) = subtract;

compute(10, 20, func);

func = add;

compute(13, 191, func);

func = divide;

compute(17, 3, func);

return 0;

}

int divide(int x, int y){
if(x % y == 0){
return x / y;
} else {
printf("warning: remainder omitted.\n");
return x / y;
}
}

int subtract(int x, int y){
return x - y;
}

int add(int x, int y){
return x + y;
}

void compute(int x, int y, int (*operation(int,int))){
printf("performing an operation on %d and %d\n", x, y);
printf("the result is %d\n", operation(x, y));
}

Using typedef, we can make our function parameter lists a little clearer. The typedef keyword enables us to create new, more complex types out of simpler types.

#include <stdio.h>

#define ARRAY_SIZE 7

typedef int (*funcPtr)(int);

int makeEven(int n);
int makeOdd(int n);
void modifyArray(int array[], funcPtr fPtr);

int main(void){

int array1[ARRAY_SIZE] = {2161, 400, 25, 636, 18, 338, 41};
int array2[ARRAY_SIZE] = {47, 3, 424, 7, 33, 1999, 8};
int i;

funcPtr fPtrOne = makeEven;
funcPtr fPtrTwo = makeOdd;

for(i = 0; i < ARRAY_SIZE; i++){
printf("%d\t", array1[i]);
}

modifyArray(array1, fPtrOne);

for(i = 0; i < ARRAY_SIZE; i++){
printf("%d\t", array1[i]);
}

printf("\nNow for the second array.\n");

for(i = 0; i < ARRAY_SIZE; i++){
printf("%d\t", array2[i]);
}

modifyArray(array2, fPtrTwo);

for(i = 0; i < ARRAY_SIZE; i++){
printf("%d\t", array2[i]);
}

}


int makeEven(int n){
if(n % 2 == 0){
return n;
} else {
return n * 2;
}
}

int makeOdd(int n){
if(n % 2 == 0){
return n * 2 - 1;
} else {
return n;
}
}

void modifyArray(int array[], funcPtr fPtr){

printf("\nmodifying array\n");
for(int i = 0; i < ARRAY_SIZE; i++){
array[i] = fPtr(array[i]);
}

}

 

 

 

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