Functions have addresses
When the compiler turns your C into machine code, each function becomes a sequence of
instructions stored starting at some address in the .text segment.
The function name, in most expressions, decays to that address — just like an array name
decays to the address of its first element.
Declaring a function pointer
The syntax is notoriously ugly. Read it from the inside out: the name is a pointer, the parentheses specify the argument types, the type before specifies the return type.
typedef int (*BinOp)(int, int); — now BinOp fp = add;
reads like a normal variable declaration. Always use typedef in real code.
The real use: callbacks
The most common use of function pointers is passing behavior to a generic function.
The C standard library's qsort works this way — it sorts anything
because you supply the comparison logic as a function pointer.
Dispatch tables
An array of function pointers is called a dispatch table.
It replaces chains of if/else or switch with direct indexing.
The kernel uses them everywhere — a system call table is an array of function pointers.
A function pointer stores a function's address. Calling through it jumps to that address — the same as any other call.