Functions, recursion and storage classes notes — Unit 3
Free unit-wise study notes on functions, recursion and storage classes for Programming for Problem Solving in C, Semester 1 of B.Tech — Computer Science & Engineering — key concepts, examples, important questions and a revision checklist for semester exams.
Twenty hand-written sheets covering functions and memory. Features exhaustive step-by-step stack traces for recursive functions and visual memory diagrams proving why Call-by-Value swapping fails.
Notebook — 20 pages
Page 1
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
1. Why Functions?
Imagine writing a 10,000-line C program inside a single `main()` function. It would be impossible to read, debug, or reuse code. A function is a self-contained block of code that performs a specific task. It takes inputs (parameters), does some work, and gives an output (return value).
Modularity
Break a massive problem into tiny, solvable pieces.
Reusability
Write the logic for `calculateTax()` once, and call it 500 times from different places.
Abstraction
You can use `printf()` without needing to know exactly how it talks to the computer monitor.
Page 2
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
2. Anatomy of a Function
A function has three crucial parts: the Declaration (Prototype), the Definition (Body), and the Call (Execution).
1. The Declaration (Prototype)
int addNumbers(int a, int b);
// Tells the compiler: 'Hey, later in this file,
// you will find a function named addNumbers.
// It takes two integers and returns an integer.'
2. The Definition (Body)
int addNumbers(int a, int b) {
int sum = a + b;
return sum;
}
// The actual logic of the function.
3. The Call (Execution)
int result = addNumbers(5, 10);
// Pauses main(), jumps to addNumbers, runs it,
// and puts the returned value (15) into 'result'.
Page 3
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
3. Parameters vs Arguments
These two terms are constantly mixed up, but examiners often test the difference.
Parameters (Formal)
The variables defined inside the function signature. They act as placeholders. Example: `int add(int x, int y)` (Here, x and y are parameters).
Arguments (Actual)
The actual, physical values you pass into the function when you call it. Example: `add(5, 10)` (Here, 5 and 10 are arguments).
Page 4
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
4. Return Types & Void
Every function must declare what TYPE of data it will hand back to whoever called it.
`int`: Returns a whole number.
`float`: Returns a decimal number.
`char`: Returns a single character.
`void`: Returns absolutely nothing.
A Void Function Example
void printGreeting(char name[]) {
printf("Hello %s!\n", name);
// No return statement needed!
}
int main() {
printGreeting("Alice");
// int x = printGreeting("Bob"); // ERROR! Can't store void.
return 0;
}
If a function is marked `void`, trying to capture its output in a variable will cause a strict compiler error.
Page 5
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
5. Call by Value vs Reference
This is the most critical concept in C memory management. When you pass a variable to a function, does the function get the REAL variable, or a PHOTOCOPY?
Call by Value
C makes a strict PHOTOCOPY of the argument. The function works on the photocopy. The original variable in `main` is 100% safe and untouched.
Call by Reference
You pass the exact MEMORY ADDRESS (pointer) of the variable. The function uses this address to directly modify the original variable in `main`.
Page 6
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
6. Dry Run: The Failing Swap
The classic 10-mark exam question asks you to explain why a basic swap function fails.
The Failing Code
void badSwap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int x = 5, y = 10;
badSwap(x, y);
printf("x = %d, y = %d", x, y); // Outputs: x = 5, y = 10
return 0;
}
1.Step 1: `main` creates local variables x=5, y=10.
2.Step 2: `badSwap(5, 10)` is called. C makes a PHOTOCOPY.
3.Step 3: `badSwap` creates its own local variables: a=5, b=10.
4.Step 4: `badSwap` successfully swaps its local 'a' and 'b'. Now a=10, b=5.
5.Step 5: `badSwap` finishes. Its local variables 'a' and 'b' are destroyed in memory.
6.Step 6: `main` prints 'x' and 'y'. They were never touched! They are still 5 and 10.
Page 7
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
7. Fixing the Swap (Reference)
To fix this, we must pass the Memory Addresses (using `&`) and receive them in Pointers (using `*`).
The Working Code
void goodSwap(int *a, int *b) {
int temp = *a; // Go to address 'a', get value.
*a = *b; // Go to 'b', copy its value into address 'a'.
*b = temp; // Put temp into address 'b'.
}
int main() {
int x = 5, y = 10;
goodSwap(&x, &y); // Pass the ADDRESS of x and y
printf("x=%d, y=%d", x, y); // Outputs: x=10, y=5
return 0;
}
Because `goodSwap` had the actual physical memory addresses of `x` and `y` from `main`, it reached directly into `main`'s memory and modified them. This is true Call by Reference.
Page 8
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
8. Passing Arrays to Functions
If C uses Call-by-Value (photocopying) for everything, what happens if you pass an array of 1,000,000 integers to a function? Does C freeze while it makes 1,000,000 photocopies? NO.
void modifyArray(int arr[]) {
arr[0] = 999; // This permanently changes the original array!
}
int main() {
int nums[3] = {1, 2, 3};
modifyArray(nums);
// nums[0] is now 999!
}
Page 9
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
9. Introduction to Recursion
Recursion is when a function calls ITSELF. It's like looking into a mirror that is reflecting another mirror.
The Two Rules of Recursion
Base Case
The condition where the function STOPS calling itself. Without this, it runs forever and crashes the program (Stack Overflow).
Recursive Step
The function calls itself with a slightly smaller/simpler input, moving closer to the Base Case.
Page 10
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
10. Dry Run: Recursive Factorial
int fact(int n) {
if (n == 1) return 1; // Base Case
return n * fact(n - 1); // Recursive Step
}
1.Let's trace `fact(4)` exactly as the computer's memory stack sees it:
2.Call 1: `fact(4)`. Is 4==1? No. Return `4 * fact(3)`.
3. -> Pauses Call 1. Starts Call 2.
4.Call 2: `fact(3)`. Is 3==1? No. Return `3 * fact(2)`.
5. -> Pauses Call 2. Starts Call 3.
6.Call 3: `fact(2)`. Is 2==1? No. Return `2 * fact(1)`.
7. -> Pauses Call 3. Starts Call 4.
8.Call 4: `fact(1)`. Is 1==1? YES. Return 1.
Page 11
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
11. Unwinding the Stack
The computer hit the base case. Now it has to 'unwind' the stack, feeding the answers back up the chain to the paused functions.
1.Call 4 finished and returned `1` back to Call 3.
2.Call 3 resumes: It was waiting for `fact(1)`. It calculates `2 * 1` = 2. Returns `2` back to Call 2.
3.Call 2 resumes: It was waiting for `fact(2)`. It calculates `3 * 2` = 6. Returns `6` back to Call 1.
4.Call 1 resumes: It was waiting for `fact(3)`. It calculates `4 * 6` = 24. Returns `24` back to main().
Page 12
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
12. Dry Run: Recursive Fibonacci
The Fibonacci sequence: 0, 1, 1, 2, 3, 5, 8... Each number is the sum of the two before it. Finding the nth term recursively is a classic exam question.
int fib(int n) {
if (n == 0) return 0; // Base case 1
if (n == 1) return 1; // Base case 2
return fib(n-1) + fib(n-2); // Recursive step
}
1.Trace `fib(3)`:
2.fib(3) = fib(2) + fib(1)
3. -> We know fib(1) = 1. But what is fib(2)?
4. -> To find fib(2), it calls fib(1) + fib(0)
5. -> We know fib(1) = 1, and fib(0) = 0. So fib(2) = 1 + 0 = 1.
6.Return to fib(3):
7.fib(3) = (1) + (1) = 2.
Page 13
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
13. Storage Classes Introduction
Every variable in C has a data type (int, float), but it also has a 'Storage Class'. This defines exactly how the variable behaves in memory.
1. Scope
Where is the variable visible? Can other functions see it, or is it hidden?
2. Lifetime
When is it created, and when is it destroyed from RAM?
3. Initial Value
If you don't initialize it (e.g., `int x;`), what value does C give it? Garbage or Zero?
4. Storage Location
Is it saved in the CPU Register, or in main RAM (Stack/Data segment)?
Page 14
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
14. 1. Automatic (auto) Variables
This is the default storage class for all local variables. If you type `int x = 5;` inside a function, C secretly treats it as `auto int x = 5;`.
Scope: Local to the block {} it is defined in.
Lifetime: Created when the block starts, destroyed instantly when the block ends.
Initial Value: Garbage value (random memory junk) if not initialized.
Storage: RAM (The Stack).
Page 15
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
15. 2. Register Variables
Accessing RAM is slow. The CPU has tiny, ultra-fast memory slots built directly into the processor chip called 'Registers'. If you have a variable you will use millions of times (like a loop counter), you can ask C to put it in a register.
register int i;
for (i = 0; i < 1000000; i++) { ... }
Scope: Local.
Lifetime: Until the block ends.
Initial Value: Garbage.
Storage: CPU Register (if available, otherwise fallback to RAM).
Page 16
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
16. 3. Static Variables
This is the examiner's favorite topic for output prediction questions. A static variable is local to a function, but it REFUSES to be destroyed when the function ends. It remembers its value for the next time the function is called.
Scope: Local to the function.
Lifetime: Entire runtime of the program.
Initial Value: EXACTLY Zero (0). No garbage!
Storage: RAM (Data Segment, not the Stack).
Initialization Rule
static int x = 5;
// This initialization line runs EXACTLY ONCE.
// On the second function call, this line is completely ignored.
1.Call 1: `count` is created and set to 0. It increments to 1. Prints '1'. Function ends, but `count` survives in memory.
2.Call 2: The `static int count = 0` line is IGNORED. `count` is currently 1. It increments to 2. Prints '2'.
3.Call 3: `count` is currently 2. Increments to 3. Prints '3'.
Page 18
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
18. 4. External (extern) Variables
Global variables (declared outside of any function) are accessible by everyone. But what if a global variable is defined in `file1.c`, and you want to use it in `file2.c`? You use `extern`.
file1.c
int playerHealth = 100; // Actually creates the variable in memory
file2.c
extern int playerHealth;
// Tells compiler: 'Don't create this variable. Trust me,
// it exists in another file. Just let me use it.'
Scope: Global (across all linked files).
Lifetime: Entire runtime of the program.
Initial Value: Zero (0).
Storage: RAM (Data Segment).
Page 19
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
19. Variable Shadowing (Scope Rules)
What happens if a local variable has the exact same name as a global variable?
int x = 100; // Global
int main() {
int x = 50; // Local
printf("%d", x);
return 0;
}
C looks for variables from the 'inside out'. It checks the current block {}, then the function, then the global scope.
Page 20
Wink Notes
B.Tech CSE — 1st Semester
Programming for Problem Solving in C
— Unit - 3 —
20. Quick Revision Checklist
⇒Unit 3 Mastery
Can you explain the difference between a Parameter and an Argument?
Can you draw the memory diagrams showing why Call-by-Value swapping fails?
Can you trace a recursive function call stack step-by-step down to the base case?
Do you know the default initial value of an 'auto' variable vs a 'static' variable?
Can you predict the output of a loop containing a static variable?
Do you understand the shadowing rules between local and global variables?