devnotes.

Function Prototypes and Recursion

Unlike some languages, C requires a function to be declared (its prototype known) before it's used — not necessarily fully defined yet.

int factorial(int n); // prototype: declares the signature, defined later

int main(void) {
    printf("%d\n", factorial(5)); // 120 — legal because the prototype above is already known
    return 0;
}

int factorial(int n) {  // full definition
    if (n <= 1) return 1;          // base case — stops the recursion
    return n * factorial(n - 1);   // recursive case — calls itself with a smaller problem
}

A prototype tells the compiler a function's name, return type, and parameter types in advance, which is why main can call factorial even though the full definition appears later in the file — without it, the compiler wouldn't know if the call is valid. In multi-file projects, prototypes typically live in header (.h) files, shared across every .c file that needs to call the function.

Recursion — a function calling itself — always needs a base case that stops the recursion (n <= 1 above) and a recursive case that moves measurably closer to that base case; without both, the function recurses forever, eventually crashing with a stack overflow once it exhausts the call stack. Recursion often produces clearer code for naturally recursive problems (tree traversal, factorial, Fibonacci), but iterative loops are usually faster and more memory-efficient in C, since each recursive call consumes additional stack space.

Function Prototypes and Recursion in C | DevNotes