› Module 5: Functions › 5.4 Storage Classes: auto, static, extern, register
M O D U L E

Module 5: Functions

Breaking a program into reusable, named blocks of logic — including how they call each other and themselves.

5.1 Function Basics: Declaration, Definition, Call

A function groups statements under a name so they can be reused. Its declaration (prototype) tells the compiler the function's name, return type, and parameter types ahead of use. Its definition supplies the actual body. A call transfers control to the function; when it hits return (or its closing brace, for void functions), control returns to the statement right after the call.

main() calls add(3, 5); Control jumps to add(int a, int b) {...} add() executes, returns a+b to caller Control returns to main() Call Stack (top->down) [ add() frame ] a=3, b=5 [ main() frame ] local vars
How a function call transfers control and uses a stack frame.

5.2 Parameter Passing: Call by Value vs Call by Reference

C is strictly call-by-value: when you pass a normal variable, the function receives a COPY, so changes inside the function never affect the caller's original variable. To let a function modify the caller's data, you pass the variable's address (a pointer) — this is how C simulates 'call by reference', and it's the mechanism scanf() relies on.

Call by Value main: x=10 copy func: a=10 (copy) changes to a do NOT affect x Call by Reference (pointer) main: x=10 (&x) address func: *p changes through *p DIRECTLY affect x
Value copies stay isolated; pointers let a function reach back into the caller's memory.

5.3 Recursion

A recursive function calls itself to solve a smaller instance of the same problem, combined with a base case that stops the recursion. Each call gets its own stack frame with its own copies of parameters and local variables; results 'unwind' back up the call chain as each call returns. Recursion is elegant for problems with a natural self-similar structure (factorial, Fibonacci, tree traversal) but costs stack memory proportional to recursion depth.

int fact(int n) {
  if (n == 0) return 1;      // base case
  return n * fact(n - 1);      // recursive case
}
fact(4) fact(3) fact(2) fact(1) -> return 1 Each call waits for the next call to return, then multiplies: fact(1) = 1 fact(2) = 2 * 1 = 2 fact(3) = 3 * 2 = 6 fact(4) = 4 * 6 = 24
fact(4) expands downward until the base case, then multiplies back upward.

5.4 Storage Classes: auto, static, extern, register

Storage classes control a variable's scope, lifetime, and default value. auto is the default for local variables (block-scoped, destroyed when the block ends). static gives a local variable a lifetime spanning the whole program (it retains its value between calls) or, for a global, restricts its visibility to the current file. extern declares that a variable/function is defined in another file, enabling sharing across translation units. register suggests (not guarantees) that a variable be kept in a CPU register for faster access.

Storage Class Storage Location Default Initial Value Scope Lifetime
autoStack FrameGarbage / UndefinedLocal blockFunction execution
staticData / BSS SegmentZero (0)Local block or Current FileEntire program lifetime
externData / BSS SegmentZero (0)Global / Multi-fileEntire program lifetime
registerCPU RegisterGarbage / UndefinedLocal blockFunction execution
MODULE COMPREHENSIVE QUIZ

Module 5 Final Quiz

Test your understanding across all 4 topics of this module with interview-grade questions, tricky edge cases, and code output predictions.

Take Module 5 Final Quiz →
Yukti Mascot