Function pointers allow great flexibility in a program. All you have to do is
  1. Take a function
    int foo(int bar)
    {
        return bar+1;
    }
  2. Take a function pointer
    int (*func)(int);
  3. Set the function pointer to the function's address
    func=foo;
  4. Then call the function pointer
    func(42);

There is some flexibility in the syntax of function pointers. You can get the address of the function using foo or &foo, and you can also choose between func(42) or (*func)(42) when calling the function pointer. I personally think of function names as pointers, so I prefer the former syntax to remain consistent with normal function calling. There's nothing you can do with the target of a function pointer besides calling it. You can, of course, make an array of function pointers.

The function pointer makes flexibility because you could put another function address into func, and then func(42) would call the other function. When you use libdl, you can load up libraries at runtime, and call functions that are in the library. This is what Apache does with its modules.