-2

The point being saying w.r.t c only, as I am more comfortable in C.

I am not expecting a example which says this is how it works ... What I am expecting is why should we use the Call back function or some say it as function pointer.

I followed many blog and stack-overflow also, but not satisfied with any of those answers.

Let's say ( I am suggesting one scenario here, like sorting thing) we should use the call back thing, where a method/function will take more time for processing.

Let's say a process is there with one thread only, and the program is doing a sorting, which will take huge time ( let's assume > 1 min ). According to huge no of bloggers here we should use the function pointer. But how it would be useful ?

Any how we are having only one Program Counter and we will get some amount of time to process this process from CPU, then how it would be useful ?

If you think some other example is there to explain the function pointer concept please provide the example.

I saw some body suggesting like, if you will use function pointer, then the result u can collect later, but this sounds really awkward ! how is this even if possible ? How can u collect something from a function after returning from there ? the function would have been destroyed right !!!

In real time people use this for any change in events, so that they can get notification...( just adding a point )

I have seen some good programmer using this function pointer, I am dying to know why would I use this , surely there is something I am missing here...

Please reply, thanks in Advance.

BUGGY
  • 1
  • 1
  • 6
    http://stackoverflow.com/search?tab=votes&q=%5bc%5d%20callback - there's dozens of explanations and examples available already. – Mat Apr 19 '15 at 11:21
  • 5
    The bottom line is when you pass a function pointer in the argument list of a function, you have the **power** to change the behavior of that function in many ways not possible by passing simple variables/or pointers. A basic example would be a `calc` function that takes a function pointer and two numbers. Without so much a passing a different function name as an argument you could have `add`, `subtract`, `multiply`, etc.. without changing anything else. It introduces flexibility in your coding and greatly expands the tools at your disposal for solving problems in new and more efficient ways. – David C. Rankin Apr 19 '15 at 11:36
  • 2
    As to "Why use it?", the truth is that until you have mastered all of the normal procedural aspects in C, you probably will not make much use of function pointers intentionally. But when you get to that point and see how they can supplement and extend the normal programming paradigm in C, you will begin to make much more use of function pointers and even arrays of function pointers to solve problems in ways that were not even in your toolbox a couple of months ago. – David C. Rankin Apr 19 '15 at 11:41
  • 2
    All I have to say is things like `int iterate_lines(FILE *fptr, char *buffer, size_t bufsize, int (*action)(const char *, size_t));` can be invaluable at times. After reading a line up to `bufsize` bytes and storing the bytes in the `buffer`, it passes that line to whatever `action` function was specified along with the length of the line (not necessarily `bufsize`), allowing for manipulation of the line, printing of the line, or whatever else you might want to do with that line. That's the beauty of the callback: in a limited fashion, you're allowed to perform an action of _your choice_. –  Apr 19 '15 at 11:56
  • @DavidC.Rankin so are you saying, function pointer is all about, the way of writing a good program but nothing more than that i,e it's only for the programmers' comfortability ? – BUGGY Apr 19 '15 at 11:58
  • "Any how we are having only one Program Counter" — please come back from 1990. – The Paramagnetic Croissant Apr 19 '15 at 12:09
  • 1
    @BUGGY Nope, sometimes you **need** it. For example, for dynamic loading (google `dlopen()` and `dlsym()`.) – The Paramagnetic Croissant Apr 19 '15 at 12:11
  • @TheParamagneticCroissant.. thanks for the dlopen and dlsym i am checking on that one now... but what do you mean by the first comment ? can you give me CPU name which is having more than one Program counters .. the last time went upto arm7... there were no more than one PC – BUGGY Apr 19 '15 at 13:03
  • @TheParamagneticCroissant are you talking about multi-core CPUs ? then need to check... still let's talk about single core CPU, as the Function pointer was well before Multi-core thing – BUGGY Apr 19 '15 at 13:22
  • Buggy, the use of function pointers is not itself about writing a good program, rather making use of function pointers **provides a way to pass (or return)** all the functionality you can put in a function **as a one word argument** throughout your code. Rather than being limited to calling a function to do some work, you use a function pointer as a variable, assigning the desired function to the pointer. This open up endless possibilities of how you can conditionally change program behavior just be changing the value of a function pointer. – David C. Rankin Apr 20 '15 at 01:06
  • 1
    callback function makes use of function pointer but function pointer is not callback pointer, they can be used for various purposes. For example a code dispatcher can have many versions of a function for different instruction sets like x86, SSE2, SSSE3, AVX... then a single function pointer can be stored and used later without the need of switching, or when you need to switch some values that doesn't change in the whole program life to select between some functions then you can simply store the function pointer and eliminate the switch completely – phuclv Apr 21 '15 at 03:50
  • possible duplicate of [What are function pointers used for, and how would I use them?](http://stackoverflow.com/questions/1758564/what-are-function-pointers-used-for-and-how-would-i-use-them) – phuclv Apr 21 '15 at 03:54
  • I agree with your comment and I didn't intend to imply that one was another or vice versa. The naming was simply intended to show one possible use, it could probably have been different... – David C. Rankin Apr 21 '15 at 04:17
  • @LưuVĩnhPhúc can you please tell me what is the difference between a function pointer and call back pointer ? – BUGGY Apr 21 '15 at 19:19
  • callback is used to call back to some function after an event like timer timed out, button pressed, GPIO changed, interrupt happened... and function pointer indicates a general use – phuclv Apr 22 '15 at 02:05

1 Answers1

0

Since there was still a bit of uncertianty in your last comment, perhaps a concrete example illustrating the points would help. Let's start with a simple example that takes a string as user input from the command line (you could prompt the user for input as well). Now let's say we want to give the user to option to tell us how they want to store the input. For purpose of this example, lets say the options are (1) to store the string normally, such that it prints on one line horizonally, (2) store the reverse of the string which will also print on one line, (3) store the string with newlines after each character so it prints vertically, and (4) store the string in reverse with embedded newlines.

In a normal approach to this problem, you would probably code a switch statement or a series of else if statements and pass the string to 4 different routines to handle the different cases. Function pointers allow you to approach the problem a little differently. Rather than 4 different input routines to handle each case, why not 1 input routine that takes a function pointer as it's argument and changes the way it handles the string based on the function passed as an argument. The input routine could be as simple as making a copy of the string (to prevent modifying argv[1], etc...) and then passing the string as an argument to a function represented by the pointer:

/* make copy of original string, pass to callback function */
char *input (char *d, char *s, char *(*cbf)(char *))
{
    strcpy (d, s);
    return (*cbf) (d);
}

The input function above takes as arguments the destination string d, the source string s and then a pointer to a funciton cbf (short for callback function). Let's look at the function pointer syntax quickly and digest what it tells us:

char *(*cbf)(char *)
  |      |     \
return   |    argument
type     |    list
         |
    function pointer
      name/label

Above, the function pointer named cbf has a return type of char *, and takes a single argument of type char *. (note: only the type is specified in the funciton pointer argument list, not both the type and argument name -- e.g. no char *str, just char *) Now that may seem like a lot to type each time you want to pass a function of that type as an argument or use it in an assignment. It is. There is an easy solution to reduce the typing required. You can use a typedef for the function pointer similar to how you use a typedef with a struct, etc. Creating a typedef of type cbf is equally easy:

typedef char *(*cbf)(char *);

The funciton pointer typedef above creates a type cbf that can be used in place of char *(*cbf)(char *) wherever the function pointer type is needed. When a typedef is used, you are relieved from specifying the return type and the argument list as well as not having to put the function pointer inside parenthesis. This reduces the original function declaration to:

char *input (char *d, char *s, cbf fname)
{
    strcpy (d, s);
    return fname (d);
}

Making use of a typedef for a function not only simplifies passing the functions as argument, but also simplifies creating arrays of funciton pointers as well. An array of funtion pointers can be used to simplify selecting and passing any one of a given number of functions, as needed. For our input function we create an array of function pointers each pointing to a different function that can be used to put the input string in the desired format. For example, let's say our 4 functions described above have declaration like this:

/* input processing callback functions */
char *hfwd (char *s);
char *hrev (char *s);
char *vfwd (char *s);
char *vrev (char *s);

note: each of the functions match our pointer definition of type char * and accept a single argument of type char *. Using our cbf typedef, we can easily create an array of function pointers called fnames as follows:

cbf fnames[] = { &hfwd, &hrev, &vfwd, &vrev };

The fnames array can then be used like any other array to select any one of our functions by array index. (e.g. fnames[0] is our function hfwd) This now gives us the ability to take a second input from our user, a number, to select the format for our input string. This provides the ability to use any one of our callback function by simply giving the array index for the desired function as the second argument on the command line. For example any one of the functions can be designated by calling out program with:

./progname my_string 1      /* to process the input with the hrev */

Now granted this example does not do much more than reformat a string, but from the standpoint of function pointer syntax, collecting function pointers in an array, and passing a function pointer as an argument to extend the capabilities of your code, it covers a great deal. Take a look at the following example, and let me know if you have any questions. (recall, the full function pointer syntax, in the absence of a typedef, is also included, but commented so you can compare/contrast typedef use)

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

#define MAXS 128

/* typedef for function pointer */
typedef char *(*cbf)(char *);

/* simple string reverse function */
char *strrevstr (char *str);

/* input processing callback functions */
char *hfwd (char *s);
char *hrev (char *s);
char *vfwd (char *s);
char *vrev (char *s);

/* input function, pointer to function will determine behavior */
// char *input (char *d, char *s, char *(*cbf)(char *));
char *input (char *d, char *s, cbf fn);

int main (int argc, char **argv) {

    if (argc < 3 ) {
        fprintf (stderr, "error: insufficient input, usage: %s string int\n", argv[0]);
        return 1;
    }

    int idx = atoi(argv[2]);

    if (idx > 3 || idx < 0) {
        fprintf (stderr, "error: invalid input -- out of range, (0 !< %d !< 3)\n", idx);
        return 1;
    }

    cbf fnames[] = { &hfwd, &hrev, &vfwd, &vrev };
    // char *(*fnames[])(char *) = { &hfwd, &hrev, &vfwd, &vrev };
    char string[MAXS] = {0};

    input (string, argv[1], fnames[idx]);

    printf ("\nProcessed input ('%s' '%s'):\n\n%s\n\n", argv[1], argv[2], string);

    return 0;
}

/* strrevstr - reverse string, original is not preserved. */
char *strrevstr (char *str)
{
    if (!str) {
        printf ("%s() error: invalid string\n", __func__);
        return NULL;
    }

    char *begin = str;
    char *end = str + strlen (str) - 1;
    char tmp;

    while (end > begin)
    {
        tmp = *end;
        *end-- = *begin;
        *begin++ = tmp;
    }

    return str;
}

/* string unchanged - print horizontal */
char *hfwd (char *s)
{ return s; }

/* string reversed - print horizontal */
char *hrev (char *s)
{ return strrevstr (s); }

/* string unchanged - print vertical */
char *vfwd (char *s)
{
    char *p = s;
    static char buf[MAXS] = {0};
    char *b = buf;

    while (*p)
    {
        *b++ = *p++;
        *b++ = '\n';
    }

    *b = 0;

    b = buf;
    while (*b)
        *s++ = *b++;
    *b = 0;

    return buf;
}

/* string reversed - print vertical */
char *vrev (char *s)
{
    char *p = strrevstr (s);
    static char buf[MAXS] = {0};
    char *b = buf;

    while (*p)
    {
        *b++ = *p++;
        *b++ = '\n';
    }

    *b = 0;

    b = buf;
    while (*b)
        *s++ = *b++;
    *b = 0;

    return buf;
}

/* make copy of original string, pass to callback function */
char *input (char *d, char *s, cbf fn)
// char *input (char *d, char *s, char *(*cbf)(char *))
{
    strcpy (d, s);
    return fn (d);
//     return (*cbf) (d);
}

Output

$ ( for i in {0..3}; do ./bin/fnc_pointer my_string $i; done )

Processed input ('my_string' '0'):

my_string


Processed input ('my_string' '1'):

gnirts_ym


Processed input ('my_string' '2'):

m
y
_
s
t
r
i
n
g


Processed input ('my_string' '3'):

g
n
i
r
t
s
_
y
m
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • Thanks for your great effort here. My understanding from the e.g is 1) I can write the same program with switch-case/if-else, may be i will get little benefit in switch case also, so again why call-back :O 2) The only thing i need to understand here is **passing a function pointer as an argument to extend the capabilities of your code, it covers a great deal.**, what do you mean by capability of your code and cover a great deal 3) Mean time i am looking at the other suggested function qsort() 4) Is ther a difference between function pointer and call back pointer ? Again thanks – BUGGY Apr 21 '15 at 19:45
  • Buggy, **passing a function pointer as an argument to extend the capabilities of your code, it covers a great deal** isn't something you can explain in a few words, it is something that comes from knowing C well enough to know when to use a function pointer or whether to use something else. The short answer is use them when they save repetitive code or they give you the ability to do something you would otherwise not be able to do. To recognize when to use them only takes one thing --- experience... – David C. Rankin Apr 22 '15 at 02:54
  • Thanks David Will lookt at it. – BUGGY Apr 22 '15 at 06:53