2

I feel like I have a pretty good handle on pointers in C. Mostly, I use them to pass arrays to functions.

But I've noticed in looking at many different code examples that it' not uncommon to see pointers to functions. It's not at all clear to me why this would be useful? Are there some classic instances where the pointer to function model is handy or essential to implement?

5
  • 1
    qsort() is an example of where function pointers are used. This allows the same sorting algorithm based on different criteria (and types). Commented Sep 11, 2012 at 15:52
  • 1
    @cnicutar what about sqrt ?? Commented Sep 11, 2012 at 15:57
  • @Eregrith How is it declared ? How does it compare elements ? --- I meant qsort. Commented Sep 11, 2012 at 15:59
  • 1
    @cnicutar you're mistaking qsort with sqrt. sqrt is Square Root function. Commented Sep 11, 2012 at 16:00
  • @Eregrith Right, sorry about that :-) Commented Sep 11, 2012 at 16:01

9 Answers 9

9

The classic example is sorting an array of elements using the qsort function. Its last argument is a function pointer to the routine that compares two elements, passed as void pointers.

void qsort(void *base,
           size_t nmemb,
           size_t size,
           int(*compar)(const void *, const void *));

Using a function pointer here is essential since the sorting routine can't be made generic enough to know how you want to compare the elements, so the function pointer is essentially a "callback" that the sort function uses to let you extend it.

[Edit] For example, suppose you had the following structure defined:

struct president {
    char * fname;
    char * lname;
    unsigned int number;
};

If you wanted to sort an array of them by their "number" field you could implement a "compar" (comparator) function as follows:

int compare_presidents(const void * v1, const void * v2) {
    struct president p1 = * ((struct president *) v1);
    struct president p2 = * ((struct president *) v2);
    return (p1.number - p2.number); // Compare by number ascending.
}

And you could sort an array of such structures as such:

qsort(presidents, num_presidents, sizeof(struct president), compare_presidents);
Sign up to request clarification or add additional context in comments.

Comments

3

Think of pointers to functions as the "stone-knives-and-bearskins" way of implementing (well, describing) what we elegantly refer to now as callbacks. The analogy isn't perfect, but that's the idea - providing a quick if rather dangerous way of calling a completely different function through a pointer reference.

Comments

1

One obvious instance is qsort. You pass it a pointer to a function that it'll use to compare items. Since it doesn't know what kind of data you're sorting, it can't really do that part on its own.

Another common example is a function that does numerical integration. You pass it a pointer to the function you want to integrate, along with lower and upper bounds, and it calls the function to find the value for various points in between those bounds to get you your answer.

Comments

1

Example 1: imagine having 5 different sorting algorithms. you just want to sort in all sorts of places, but you don't want to select between the 5 in each and every place you do it. instead, you have a pointer to the sorting algorithm (they all take the same parameters, types, etc.). simply select an algorithm once (set the pointer) and use the pointer to sort everywhere.

Example 2: callback... a function does something in a loop but needs application feedback every iteration. to that function, the callback is a function pointer that's passed as an argument.

Comments

1

A very common use is for a callback function for event handlers. For example, think of a button press handler. Your button_update() may look something like:

void button_update(struct button* button, void* data) {
    if (button_pressed(button)) {
        button.callback(data);
    }
}

In this case, button.callback would be a function pointer.

Comments

1

Starting threads is another example. Similar to POSIX, C11 has interfaces for starting a thread:

typedef int (*thrd_start_t)(void*);
int thrd_create(thrd_t *, thrd_start_t, void *);

Here the thrd_start_t function pointer points to a function that will be executed by the new thread and the void* argument is the argument that is passed to that function.

Comments

1

Another common use case for function pointers is plugins. A plugin can be implemented as a dynamically loadable library. When the application loads a plugin, it can call a predefined function, passing in a struct with application function pointers, and get back a struct with plugin function pointers. Now the plugin and the application can call each other's functions.

Comments

1

Even more: function pointers also have types given by the function signature. You can also [carefully] cast into specific function pointer type:

In qsort example, the comparator expected has const void* in signature:

int (*comparator)(const void *, const void *).

However if you've a compare function for the specific (not void*) ptr type, you may simply cast it into qsort expected signature:

(int (*)(const void *, const void *))cmpr_specific

Similarly, typedef can be used to define signature for function pointers, thus saving the pain of counting parens:

typedef int (*MYFUNC_T)(int arg); MYFUNC_T callptr = myfunc; callptr(10);

,where myfunc is concrete int myfunc(int arg)

Now think what is it defined as: int (*fptr_arr[10])(int (*)(int)); ?

Well, typedefs make it legible: typedef int (*FUNC_T)(int arg); typedef int (*FUNC2_T)(FUNC_T func); -- a function that takes a function pointer argument.

FUNC2_T fptr_arr[10]; fptr_arr[0]=myfunc;

Comments

-1

Yet another example is with some heavy duty systems programming or real time embedded programming. A processor interrupt vector table can be implemented as an array of function pointers. They are implemented that way in assembler and it can also be done in C if you have a (non C Standard) way of specifying the memory location of the function table.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.