views:

271

answers:

10

I understand I can use pointers for functions.

Can someone explain why one would use them, and how? Short example code would be very helpful to me.

A: 

Another usage for pointers is iterating lists or arrays.

Dmitri Farkov
Not for function pointers. Read the question.
Chris Lutz
using function pointers in iterators is perfectly valid there is an example here: http://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work/840669#840669
Nick
Thank you, Nick!
Dmitri Farkov
+9  A: 

One quite common use case is a callback function. For example if you load something from a DB you can implement your loading function so that it reports the progress to a callback function. This can be done with function pointers.

mxp
A favorite of mine. But not just to report the progress--to actually pass back all the records!
John Zwinck
+9  A: 

A simple case is like this: You have an array of operations (functions) according to your business logic. You have a hashing function that reduces an input problem to one of the business logic functions. A clean code would have an array of function pointers, and your program will deduce an index to that array from the input and call it.

Here is a sample code:

typedef void (*fn)(void) FNTYPE;
FNTYPE fn_arr[5];

fn_arr[0] = fun1; // fun1 is previously defined
fn_arr[1] = fun2;
...

void callMyFun(string inp) {
    int idx = decideWhichFun(inp); // returns an int between 0 and 4
    fn_arr[idx]();
}

But of course, callbacks are the most common usage. Sample code below:

void doLengthyOperation(string inp, void (*callback)(string status)) {
  // do the lengthy task
  callback("finished");
}

void fnAfterLengthyTask(string status) {
    cout << status << endl;
}

int main() {
    doLengthyOperation(someinput, fnAfterLengthyTask);
}
Joy Dutta
+3  A: 

Callbacks. I make an asynchronous call to a chunk of code and want it to let me know when it finishes, I can send it a function pointer to call once it's done.

tloach
+3  A: 

You use a function pointer when you need to give a callback method. One of the classic example is to register signal handlers - which function will be called when your program gets SIGTERM (Ctrl-C)

Here is another example:

// The four arithmetic operations ... one of these functions is selected
// at runtime with a switch or a function pointer
float Plus    (float a, float b) { return a+b; }
float Minus   (float a, float b) { return a-b; }
float Multiply(float a, float b) { return a*b; }
float Divide  (float a, float b) { return a/b; }

// Solution with a switch-statement - <opCode> specifies which operation to execute
void Switch(float a, float b, char opCode)
{
   float result;

   // execute operation
   switch(opCode)
   {
      case '+' : result = Plus     (a, b); break;
      case '-' : result = Minus    (a, b); break;
      case '*' : result = Multiply (a, b); break;
      case '/' : result = Divide   (a, b); break;
   }

   cout << "Switch: 2+5=" << result << endl;         // display result
}  

// Solution with a function pointer - <pt2Func> is a function pointer and points to
// a function which takes two floats and returns a float. The function pointer
// "specifies" which operation shall be executed.
void Switch_With_Function_Pointer(float a, float b, float (*pt2Func)(float, float))
{
   float result = pt2Func(a, b);    // call using function pointer

   cout << "Switch replaced by function pointer: 2-5=";  // display result
   cout << result << endl;
}

You can learn more about function pointers here http://www.newty.de/fpt/index.html

If you are more familiar with object-oriented languages, you can think of it as C's way to implement the strategy design pattern.

David Rabinowitz
Would +1 if the C language had `cout << endl` (and also your C++ code needs to be `using namespace std;` for that to work)
Chris Lutz
Where is the mention of `opcode` in your `Switch_With_Function_Pointer()` function ?
Joy Dutta
@Joy - In the `switch()` statement.
Chris Lutz
A: 

Do you mean use pointers in the sense that you can pass pointers to functions or use pointers to point to functions (function pointers)?

You need to use pointers with functions that are intended to modify data passed to them, since C duplicates the parameters you pass to it on the stack. A swap function like this would not modify the original data:

void swap(int a, int b)
{
  int temp = a;
  a = b;
  b = temp;
}

However, this swap function would, since it is modifying the data pointed to, not the duplicated data:

void swap(int *a, int *b)
{
  int temp = *a;
  *a = *b;
  *b = temp;
}

Function pointers are also a powerful concept; you can use them as callbacks to get your code to be called in the middle of another function. For example, if you are using an event-based system, you could register a function to be called when a particular event happens by giving the event system a pointer to the function you want to be called.

Reuben
A: 

Let's do a map-like function for C.

void apply(int *arr, size_t len, int (*func)(int))
{
    for(size_t i = 0; i < len; i++)
        arr[i] = func(arr[i]);
}

That way, we can transform a function that works on integers to work on arrays of integers. We could also do a similar version:

void apply_enumerated(int *arr, size_t len, int (*func)(size_t, int))
{
    for(size_t i = 0; i < len; i++)
        arr[i] = func(i, arr[i]);
}

This does the same thing, but allows our function to know which element it's on. We could use this, for example:

int cube(int i) { return i * i * i }

void print_array(int *array, size_t len, char *sep)
{
    if(sep == NULL) sep = ", ";
    printf("%d", *array);
    for(size_t i = 1; i < len; i++) printf("%s%d", sep, array[i])
}

#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))

int main(void)
{
    int array[5] = { 1, 2, 3, 4, 5 };
    print_array(array, ARRAY_SIZE(array), NULL);
    apply(array, ARRAY_SIZE(array), cube);
    print_array(array, ARRAY_SIZE(array), NULL);
    return 0;
}

That code will print:

1, 2, 3, 4, 5
1, 8, 27, 64, 125

For our enumeration example:

int mult(size_t i, int j) { return i * j }

// print_array and ARRAY_SIZE as before

int main(void)
{
    int array[5] = { 1, 2, 3, 4, 5 };
    print_array(array, ARRAY_SIZE(array), NULL);
    apply_enumerated(array, ARRAY_SIZE(array), mult);
    print_array(array, ARRAY_SIZE(array), NULL);
    return 0;
}

This prints:

1, 2, 3, 4, 5
0, 2, 6, 12, 20

As a more real world example, a string library could have a function that applies a function that operates on single characters to all the characters in the string. An example of such functions are the standard-library toupper() and tolower() functions in ctype.h - we could use this string_apply() function to make a string_toupper() function easily.

Chris Lutz
+1  A: 

I'm surprised no one mentioned "state machines". Function pointers are a very common way to implement state machines for tasks such as parsing. See for example: link.

Angelo
A: 

A very good and easy to understand tutorial: http://www.newty.de/fpt/index.html

Hope this helps.

Kavitesh Singh
A: 

For code, check out qrdl's response to http://stackoverflow.com/questions/1371460/state-machines-tutorials.

I've used a variant of his method to implement a a menu for an LCD display I have on a board. Very very useful, makes the coding much cleaner and easier to read. Using function pointers makes expanding the number, names and ordering of menus very easy, and hides all those details from the higher level calling function that just sees 'hey, I write to the LCD here.'

ArielP