CFunction Scope & Local Variables

Function Scope & Local Variables

A local variable is any variable declared inside a function (including inside its parameter list). Local variables are the default, everyday kind of variable in C, and understanding exactly how they come into existence and disappear is essential for reasoning correctly about your programs.

Locals exist only within their function or block

A local variable's name is only visible from the point it's declared to the end of the enclosing block. Once execution leaves that block, the name is gone — you simply cannot refer to it anymore, and trying to would be a compile error:

C
void example(void) {
    int local_var = 10;
    /* local_var is visible here */
}

/* local_var is NOT visible here -- this would be a compile error:
   printf("%d", local_var);
*/
Locals are not preserved between calls

Every time a function is called, its ordinary (non-static) local variables are created fresh, with no memory of any previous call. Whatever initial value you gave them is applied again from scratch:

C
#include <stdio.h>

void increment_and_print(void) {
    int counter = 0; /* re-initialized to 0 on every single call */
    counter++;
    printf("%d\n", counter);
}

int main(void) {
    increment_and_print(); /* prints 1 */
    increment_and_print(); /* prints 1 again, not 2 */
    increment_and_print(); /* prints 1 again */
    return 0;
}
1
1
1

If you need a variable that does remember its value across calls, that's exactly what the static storage class is for — see the Storage Classes page for the full picture, including the worked counter example that contrasts directly with this one.

Local variables live on the stack

Ordinary local variables have automatic storage duration: the compiler arranges for their memory to be carved out of the program's call stack the moment execution enters their block, and automatically reclaimed the moment execution leaves it — no malloc/free involved, and no action required from you. This is also why recursion works without you manually managing memory for each call's variables: each active call gets its own independent stack space for its locals.

Worked example: independent values across two calls

Because each call gets its own fresh block of stack memory, two calls to the same function can hold completely different values in variables that share the exact same name, with zero interference between them:

C
#include <stdio.h>

void set_and_show(int input) {
    int doubled = input * 2; /* a brand-new "doubled" every call */
    printf("input = %d, doubled = %d (address: %p)\n",
            input, doubled, (void *)&doubled);
}

int main(void) {
    set_and_show(5);
    set_and_show(100);
    return 0;
}
/* Both calls print a correct, independent "doubled" value. On many
   platforms the printed address will even be identical for both calls,
   since the previous call's stack frame has already been reclaimed and
   reused by the time the next call begins. */
Never return the address of a local variable
Once a function returns, its local variables' stack memory is considered free for reuse by the next function call — the values are not "cleared," but nothing protects them either. Returning a pointer to a local variable and then dereferencing it after the function has returned is undefined behavior, even though it may appear to "work" in a quick test.
Function parameters are local variables too
A function's parameters behave exactly like local variables declared at the top of the function body: they're created fresh on each call (as copies of whatever was passed in, since C passes arguments by value), and they disappear when the function returns.