0

Yesterday I learned of this really cool way to use function pointers. Although I think its a really cool thing to be able to do I cant see WHY and WHERE this sort of method will be used?

Could someone shed some light on this?

int Mul(int x , int y)
{
return x*y;
}

int Div(int x , int y)
{ return x/y;
}

typedef int (*FuncP)(int,int);

int compu(FuncP functionP, int x , int y)
{return functionP(x , y)}

//Calling it will look like

compu(Mul,5,10);

Thanks Cart

leppie
  • 115,091
  • 17
  • 196
  • 297
  • They can be used as a callback function in event-driven programming amongst a variety of other things – K Mehta May 30 '14 at 06:07

2 Answers2

1

Pointers to functions has multiple uses but, sticking to your example, pointer to funcions can help you to avoid hurge and ugly conditional branches like if's and switches:

If you create an associative array of operations characters as index and pointer to functions as value:

//implementacion in C doesn't matter for the example
operations["*"] = Mul;
operations["/"] = Div;
operations["*"] = Add;
operations["-"] = Sub;

You can do something like this:

int op1;
int op2;
char operation;

cout << "Insert first number /n";
cin >> op1;
cout << "Insert second number /n";
cin >> op2;
cout << "Insert operator /n";
cin >> operation;
cout >> compu(operations[operation],op1,op2);
jlvaquero
  • 8,571
  • 1
  • 29
  • 45
  • 3
    Using c++ I don't believe you can have a variable named `operator` :P – DanZimm May 30 '14 at 06:36
  • @DanZimm You are right! I was writing the example from the top of my head and didn't think about keywords. Good point. Anyway I was using C++ for simplicity and fast prototype with stardad input not for any special reason. – jlvaquero May 30 '14 at 06:46
  • all good, just was bustin chops ;D – DanZimm May 30 '14 at 06:46
1

If you need something to be dynamic based on a situation like so:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <stdbool.h>

typedef int (*worker_operation)(int);

int check_for_new_woot(int inVal) {
  int ret = arc4random() % 10;
  if (ret < 5) {
    puts("Found new woot!");
    sleep(1);
    return 1;
  } else {
    puts("No new woot :(");
    sleep(1);
    return 0;
  }
}
int buy_current_woot(int inVal) {
  if (inVal != 0) {
    fprintf(stderr, "Insufficient funds!!!\n");
  }
  return 0;
}

int check_if_should_buy_woot(int inVal) {
  printf("Should we buy the latest woot? ");
  char input[10];
  read(STDIN_FILENO, input, 10);
  if (input[0] == 'y') {
    return 1;
  } else {
     return 0;
  }
}

void *worker_thread(void *inVal) {
  worker_operation *ops = (worker_operation *)inVal;
  int i = 0;
  worker_operation op = ops[i];
  int arg = 0;
  while (op) {
    arg = op(arg);
    op = ops[++i];
  }
  free(ops);
  return NULL;
}

pthread_t start_worker(worker_operation *ops) {
  pthread_t pt;
  pthread_create(&pt, NULL, worker_thread, ops);
  return pt;
}

int main(int argc, const char *argv[]) {
  bool autoBuy = true; // fetch whether we should automatically buy from woot.com from argv or stdin
  int numberLoops = 10; // fetch number of times to loop through the process
  int i;
  worker_operation *operations;
  if (autoBuy) {
    operations = (worker_operation *)malloc(sizeof(worker_operation) * (numberLoops * 2 + 1));
    for (i = 0; i < numberLoops; i++) {
      operations[2 * i] = check_for_new_woot;
      operations[2 * i + 1] = buy_current_woot;
    }
    operations[2 * i] = (worker_operation)NULL;
  } else {
    operations = (worker_operation *)malloc(sizeof(worker_operation) * (numberLoops * 3 + 1));
    for (i = 0; i < numberLoops; i++) {
      operations[3 * i] = check_for_new_woot;
      operations[3 * i + 1] = check_if_should_buy_woot;
      operations[3 * i + 2] = buy_current_woot;
    }
    operations[3 * i] = (worker_operation)NULL;
  }
  pthread_join(start_worker(operations), NULL);
  return 0;
}

Note that in this code snippet uses function pointers in two places. We have a function which is agnostic of how the user wants the program to perform, that is start_worker simply creates a worker thread that will work with a list of operations. This can be easily used to create a program which has multiple threads going all with different operation queues. The second place function pointers are used are with threads. The ptrhead_create call uses a function pointer in order to create a new thread (the function specified is the function to be ran on the new thread).

Generally this is called a command programming paradigm. One can easily create an operation that another part of code can call, agnostic of what the function does. For instance this could be useful for games in the following situation:

We have a game controller that gives input. The user clicks 'up'. In code call the operation that is hooked to the 'up' action.

This modular approach allows one to enable settings for the controls so someone can hook a 'jump' operation to 'up' or a 'move forward' operation, or anything really.

Hope this helps!

DanZimm
  • 2,528
  • 2
  • 19
  • 27