Functions: Declaration, Definition, Call, Parameters, Return Values, Recursion, Scope and Storage Classes
This domain tests how C breaks a program into functions, how arguments actually reach a function, what a function may return, and how long a variable lives and who can see it.
Declarations, definitions and calls
A prototype tells the compiler the name, parameter types and return type: int add(int a, int b);. The definition supplies the body: int add(int a, int b) { return a + b; }. Calling a function with no visible prototype is an error in C99 (C89 assumed int). C passes every argument by value, so the function receives copies; to let it modify the caller's variable, pass the address and dereference a pointer.
Return values, scope and storage classes
return expr; ends the function and converts expr to the declared return type; a void function uses a bare return; or none. C has block scope (locals, parameters), function scope (labels) and file scope (globals). Storage classes: auto is the default for locals; register is a hint and forbids taking the address; static on a local keeps its value between calls, while at file scope it gives internal linkage; extern declares a name defined elsewhere.
Recursion
A recursive function calls itself and needs a base case plus progress toward it: int fact(int n) { return n <= 1 ? 1 : n * fact(n - 1); }. fact(4) evaluates 4×3×2×1 = 24. Every call consumes stack space, so deep recursion can overflow.
Worked example
void swap(int a, int b) { int t = a; a = b; b = t; }
Calling swap(x, y) leaves x and y unchanged, because only the copies are swapped. The working version takes int *a, int *b, swaps *a and *b, and is called as swap(&x, &y).
Traps
- Returning the address of a local variable leaves a dangling pointer.
- Writing
int f();when you meanint f(void);for a parameterless function. - Believing a
staticlocal is visible outside its function - it is not. - Passing too few or too many arguments to a prototyped function.