[C] Can someone explain me pointers to functions?

What does it do, exactly?

What it does is remarkably simple, but it depends a lot on how calling C functions work so I'll make a quick detour through that.

For simplicity, imagine there is a single process running on your computer (there isn't, but the operating system makes every process believe it is). The CPU is munching it away, instruction by instruction: it loads and executes an instruction at that address, then at address adjacent to it and so on. A function call happens (broadly) as follows:

  • The arguments of that function are pushed on the stack (a memory region reserved exactly for pushing and poping things on it, and you have a pointer to its head in one of the CPU's registers)
  • The caller "jumps" at the address where the first instruction of the function is stored (i.e. the next address the CPU executes an instruction from isn't the one that follows after the current one, but the address of the first instruction in the function)
  • Now the function does whatever it wants to do (it finds its arguments on the stack), stores the return value "somewhere safe", and jumps back at the address after the the caller's jump instruction.

There are a lot of elements that vary in this description (such as where the arguments are stored and in what order) but the basic point is that function execution happens by putting the arguments in well-defined place and well-defined order, jumping to the function's body, then returning execution to the prior place.

So, how do function pointers work: they store the address of the first instruction in the function :).

When you call a function, the CPU jumps to the address of that function's first instruction. When you call a pointer to a function, the CPU jumps to the address stored in that pointer -- which is actually the function's first instruction.

When would it be useful?

I... am not sure exactly where to start from, so I'll give you just one example, I think you'll get the point easily. The general "rule", if you wish, is "it's used when you want to decide at runtime what function you're going to run".

Imagine you're writing a GUI library -- and more specifically, a push button widget. You're even more specifically trying to solve the problem of how you're going to let the programmer specify what will happen when the button is clicked. There are a lot of ways to do that, but one of them (admittedly, very clean) is as follows:

  1. Have the user specify the pointer to a function that he wants ran when the button is clicked, store that along with all other information about the button, e.g.:

    struct button { int x, y; /* Position within parent / void (clicked)(void ); / Handler for clicked event */ ... }

  2. Have every click on that button add an event to a queue of events; the event could look like this:

    struct widget_event { event_type_t type; /* What happened? / void *widget; / What widget was the subject to an user action? / void (handler)(void ); / What function will be handling this event? */ }

(I know the first member of the structure seems redundant; it's not always the case).

  1. And in the GUI's loop, dequeue events and execute them.

This way, the user can write something like this:

void quit_function(void *data) {
    /* Cleanup */
   ...
    /* Quit application */
    app->exit = true;
}

struct button quit_btn = { 10, 10, /* whatever */
                                       quit_function }
window_add_widget(main_window, quit_btn);
...
/r/learnprogramming Thread