Phase 2 — Control Flow & Functions
Phase 2 is where C starts behaving like a real programming language rather than just a collection of statements.
We’ll cover the whole phase in 10 chapters:
if,else,else if+ truth in CNested conditions
switchwhiledo whilefor+ nested loopsbreak,continue, infinite loops + off-by-one errorsFunctions, parameters, arguments, return values,
voidPrototypes, scope, local/global variables + pass-by-value
Recursion
Chapter 1 — if, else, else if & Truth in C
Question
Given below is a program that checks a person's score.
Predict the output before reading the explanation.
#include <stdio.h>
int main(void)
{
int score = 72;
// Check the first condition.
if (score >= 90)
printf("Excellent\n");
// Check this condition if the first one was false.
else if (score >= 60)
printf("Pass\n");
// Execute this if all previous conditions were false.
else
printf("Fail\n");
// C treats non-zero values as true and 0 as false.
if (5)
printf("Five is true\n");
if (0)
printf("Zero is true\n");
return 0;
}Answer
Pass
Five is trueStep-by-step explanation
score is 72.
First:
score >= 90becomes:
72 >= 90which is false.
So C moves to:
score >= 60which becomes:
72 >= 60true.
Therefore:
printf("Pass\n");runs.
The else is skipped because one previous condition succeeded.
The second important concept is:
if (5)In C:
0→ falseany non-zero value → true
Therefore 5 is true.
But:
if (0)is false.
How to read the important code
When you see:
if (condition)read it naturally as:
"If this condition is true, execute the following statement/block."
For:
else if (...)read:
"Otherwise, if this new condition is true..."
Beginner trap
C does not have a special Boolean requirement for if.
This is perfectly valid:
if (123)and this is also valid:
if (-10)Both are true because they are non-zero.
Key takeaway
In C,
0is false and every non-zero value is true.
Chapter 2 — Nested Conditions
Question
What will this program print?
#include <stdio.h>
int main(void)
{
int age = 20;
int has_id = 1;
// First check whether the person is old enough.
if (age >= 18)
{
// Only people who are at least 18 reach this block.
if (has_id)
{
printf("Entry allowed\n");
}
else
{
printf("ID required\n");
}
}
else
{
printf("Too young\n");
}
return 0;
}Answer
Entry allowedStep-by-step explanation
Start with:
age = 20Check:
age >= 1820 >= 18 → true.
So we enter the outer if.
Now C checks:
if (has_id)has_id is 1.
Since non-zero means true:
1 → trueTherefore:
Entry allowedis printed.
How to read the important code
Think of nested ifs as gates:
Gate 1
↓
Gate 2
↓
ActionThe inner condition is never evaluated if the outer condition prevents execution from reaching it.
Beginner trap
Don't confuse:
if (age >= 18)with:
if (age = 18)The first compares.
The second assigns.
Key takeaway
A nested
ifis simply anifinside another decision block.
Chapter 3 — switch
Question
Predict the output.
#include <stdio.h>
int main(void)
{
int day = 3;
// Select one case based on the value of day.
switch (day)
{
case 1:
printf("Monday\n");
break;
case 2:
printf("Tuesday\n");
break;
case 3:
printf("Wednesday\n");
break;
case 4:
printf("Thursday\n");
break;
default:
printf("Unknown day\n");
}
return 0;
}Answer
WednesdayStep-by-step explanation
day contains:
3C enters the switch:
switch (day)It searches for:
case 3:It finds it and executes:
printf("Wednesday\n");Then:
break;terminates the switch.
Why is break important?
Consider:
case 3:
printf("Wednesday\n");
case 4:
printf("Thursday\n");Without break, execution can fall through into the next case.
So normally:
case 3:
...
break;is used when you don't want fall-through.
default
default is similar to the "none of the above" branch.
For example:
day = 10;would produce:
Unknown dayHow to read the important code
Read:
switch (day)as:
"Choose an execution path based on the value of
day."
Key takeaway
Use
switchwhen one expression needs to be matched against multiple discrete values.
Chapter 4 — while
Question
What is the output?
#include <stdio.h>
int main(void)
{
int count = 1;
// Repeat while count is less than or equal to 5.
while (count <= 5)
{
printf("%d ", count);
// Change the condition's variable.
count++;
}
return 0;
}Answer
1 2 3 4 5Step-by-step explanation
Initially:
count = 1C checks:
count <= 5true → print 1.
Then:
count++;makes:
count = 2The condition is checked again.
This continues:
1 → print
2 → print
3 → print
4 → print
5 → print
6 → stopThe important point is that the condition is checked before each iteration.
How to read the important code
Read:
while (condition)as:
"Keep doing this while the condition remains true."
Beginner trap
A while loop can accidentally become infinite:
int count = 1;
while (count <= 5)
{
printf("%d", count);
}count never changes.
Therefore the condition remains true forever.
Key takeaway
whilechecks the condition first, then executes the loop body.
Chapter 5 — do while
Question
What does this program print?
#include <stdio.h>
int main(void)
{
int number = 10;
// Execute the body first.
do
{
printf("Number = %d\n", number);
number++;
}
// Check the condition after execution.
while (number < 5);
return 0;
}Answer
Number = 10Step-by-step explanation
Initially:
number = 10The do block executes without checking the condition first.
So:
printf("Number = %d\n", number);prints:
Number = 10Then:
number++;makes number equal to 11.
Only now does C check:
number < 511 < 5 → false.
The loop ends.
while vs do while
while:
check → execute → check → execute
do while:
execute → check → execute → checkTherefore a do while loop executes at least once.
Key takeaway
do whileexecutes the body first and checks the condition afterward.
Chapter 6 — for Loops & Nested Loops
Question
Predict the output.
#include <stdio.h>
int main(void)
{
// Outer loop controls the rows.
for (int row = 1; row <= 3; row++)
{
// Inner loop controls the columns.
for (int column = 1; column <= row; column++)
{
printf("* ");
}
printf("\n");
}
return 0;
}Answer
*
* *
* * * Step-by-step explanation
The outer loop starts:
row = 1Inner loop:
column = 1Since:
1 <= 1one star is printed.
Next:
row = 2The inner loop runs twice:
* *Next:
row = 3The inner loop runs three times:
* * *How to read a nested loop
Think:
outer loop
inner loop
inner loop
inner loop
outer loop
inner loop
inner loop
inner loopThe inner loop completes its entire execution for each iteration of the outer loop.
The three parts of for
for (initialization; condition; update)Here:
for (int row = 1; row <= 3; row++)means:
start → row = 1
continue while → row <= 3
after each iteration → row++Key takeaway
A
forloop packages initialization, condition, and update into one compact loop structure.
Chapter 7 — break, continue, Infinite Loops & Off-by-One Errors
Question
Predict the output.
#include <stdio.h>
int main(void)
{
for (int i = 1; i <= 10; i++)
{
// Skip even numbers.
if (i % 2 == 0)
continue;
// Stop when i reaches 7.
if (i == 7)
break;
printf("%d ", i);
}
return 0;
}Answer
1 3 5Step-by-step explanation
i = 1
Odd → continue condition false.
i == 7 false.
Print:
1i = 2
i % 2 == 0is true.
So:
continue;skips the remaining body.
2 is not printed.
i = 3
Print:
3i = 4
Skipped.
i = 5
Printed.
i = 6
Skipped.
i = 7
The first condition is false because 7 is odd.
Then:
if (i == 7)
break;is true.
break terminates the loop immediately.
Therefore 7 isn't printed.
continue vs break
continue:
Skip the current iteration and move toward the next one.
break:
Leave the loop completely.
Infinite loops
A deliberately infinite loop can be written as:
for (;;)
{
/* runs forever */
}This is sometimes useful in systems programming, servers, embedded programs, event loops, etc.
But accidental infinite loops are bugs.
Off-by-one errors
Suppose you want numbers 1 through 5:
for (int i = 1; i < 5; i++)This gives:
1 2 3 4because 5 < 5 is false.
Whereas:
for (int i = 1; i <= 5; i++)gives:
1 2 3 4 5This is an off-by-one error.
Key takeaway
breakexits;continueskips the current iteration; carefully check<versus<=.
Chapter 8 — Functions, Parameters, Arguments, Return Values & void
Question
What will this program print?
#include <stdio.h>
// Function declaration.
int add(int a, int b);
int main(void)
{
int result;
// 10 and 20 are arguments.
result = add(10, 20);
printf("%d\n", result);
return 0;
}
// Function definition.
int add(int a, int b)
{
// Return a value to the caller.
return a + b;
}Answer
30Step-by-step explanation
Execution begins in:
main()This line:
result = add(10, 20);calls the function.
The values:
10
20are arguments.
Inside the function:
int add(int a, int b)a receives 10.
b receives 20.
Therefore:
return a + b;becomes:
return 10 + 20;which returns:
30That returned value is assigned to:
resultThen:
printf("%d\n", result);prints 30.
Parameter vs argument
Consider:
int add(int a, int b)a and b are parameters.
When calling:
add(10, 20)10 and 20 are arguments.
Think:
parameter → variable defined by the function
argument → actual value supplied during the callvoid
A function that doesn't return a value can use:
voidFor example:
void greet(void)The first void means:
returns nothing
The second void means:
accepts no arguments
This is why:
int main(void)means:
mainreturns anintand takes no arguments.
Key takeaway
Functions package reusable behavior; parameters receive values and
returnsends a value back to the caller.
Chapter 9 — Prototypes, Scope, Local/Global Variables & Pass-by-Value
Question
Predict the output carefully.
#include <stdio.h>
// Global variable.
int value = 100;
// Function prototype.
void change(int number);
int main(void)
{
int value = 10;
printf("Before: %d\n", value);
// Pass value to the function.
change(value);
printf("After: %d\n", value);
return 0;
}
void change(int number)
{
// This changes only the function's local copy.
number = 999;
printf("Inside: %d\n", number);
}Answer
Before: 10
Inside: 999
After: 10Step-by-step explanation
There are two different variables named value.
Global:
int value = 100;Local to main:
int value = 10;Inside main, the local variable is the one being used.
So:
printf("Before: %d\n", value);prints:
10Then:
change(value);passes 10 to the function.
The parameter:
int numberreceives a copy of 10.
Inside the function:
number = 999;changes that copy.
So:
Inside: 999is printed.
But the original value in main remains:
10Therefore:
After: 10Pass-by-value
C fundamentally passes function arguments by value.
That means:
main's value
↓
copy
↓
function parameterChanging the parameter doesn't change the original variable.
Pointers will later give us a way for a function to modify the caller's object.
Scope
Scope means, roughly:
Where can this variable name be accessed?
This:
int main(void)
{
int x = 10;
}creates a local variable whose scope is inside that block.
A global variable can have broader scope, but globals should not be treated as a substitute for good program design.
Function prototype
This:
void change(int number);is a function declaration/prototype.
It tells the compiler:
"There is a function called
change; it takes anintand returnsvoid."
The actual implementation comes later:
void change(int number)
{
...
}Why prototypes matter
C compiles source code in a structured way. The compiler needs to know enough about a function when it encounters a call.
Key takeaway
C passes arguments by value; without pointers, changing a parameter doesn't directly change the caller's variable.
Chapter 10 — Recursion
Question
Predict the output.
#include <stdio.h>
// Calculate n! recursively.
int factorial(int n)
{
// Base case: stop recursion.
if (n <= 1)
return 1;
// Recursive case: function calls itself.
return n * factorial(n - 1);
}
int main(void)
{
printf("%d\n", factorial(4));
return 0;
}Answer
24Step-by-step explanation
Start:
factorial(4)becomes:
4 * factorial(3)Then:
4 * 3 * factorial(2)Then:
4 * 3 * 2 * factorial(1)Now the base case:
if (n <= 1)
return 1;returns 1.
So the calculations unwind:
factorial(1) = 1
factorial(2) = 2 × 1 = 2
factorial(3) = 3 × 2 = 6
factorial(4) = 4 × 6 = 24Therefore:
24Two essential parts of recursion
Every useful recursive function needs a way to eventually stop.
1. Base case
if (n <= 1)
return 1;2. Recursive case
return n * factorial(n - 1);The recursive call moves toward the base case.
What happens in memory?
This is especially important because later we'll connect recursion to stack frames.
Conceptually:
factorial(4)
↓
factorial(3)
↓
factorial(2)
↓
factorial(1)Each active function call needs its own call information.
Later, when we study memory, pointers and stack frames, you'll understand exactly what is happening underneath.
Beginner trap
This would be dangerous:
int factorial(int n)
{
return n * factorial(n - 1);
}There is no base case.
The function keeps calling itself until the program eventually runs out of stack space.
Key takeaway
Recursion means a function calls itself, and a base case is required to stop the chain.
Phase 2 — What You Should Now Understand
You have now covered the complete Phase 2 roadmap:
| Concept | Core idea |
|---|---|
if | Make a decision |
else | Alternative path |
else if | Test another condition |
| C truth | 0 false, non-zero true |
Nested if | Decision inside decision |
switch | Match one expression against cases |
while | Check → execute |
do while | Execute → check |
for | Initialization → condition → update |
| Nested loops | Loop inside another loop |
break | Exit loop |
continue | Skip current iteration |
| Infinite loop | Condition never becomes false |
| Off-by-one | Boundary/counting mistake |
| Function | Reusable block of code |
| Parameter | Variable receiving an argument |
| Argument | Value supplied to a function |
return | Send a value back |
void | No value / no parameters |
| Prototype | Tells compiler about a function |
| Scope | Where a name is accessible |
| Local variable | Variable belonging to a block/function |
| Global variable | Variable declared outside functions |
| Pass-by-value | Function receives a copy |
| Recursion | Function calls itself |
The most important connection
Phase 2 should leave you with this mental model:
C PROGRAM
│
┌────────┴────────┐
↓ ↓
DECISIONS REPETITION
│ │
if / switch while / for
│ │
└────────┬────────┘
↓
FUNCTIONS
│
┌────────┴────────┐
↓ ↓
parameters return
│ │
└────────┬────────┘
↓
REUSABLE LOGIC
│
↓
recursionOne crucial bridge to Phase 3/4
You have also reached an important point:
change(value);cannot directly modify value because C passed a copy.
Soon, when we reach pointers, the picture changes:
value
│
└── address ──→ pointer ──→ same memoryThat is where C becomes substantially different from Java—and where Phase 4 becomes one of the most important parts of your entire C journey.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.