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:
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:
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 */ ... }
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).
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);
...