Recommended resources
The freely available resources this lesson will direct you to.
Welcome to the final lesson in our module on controlling program flow. In our last session, we learned how to use break and continue to gain precise control over for and while loops, allowing us to exit early or skip specific iterations.
So far, all our loops have been single-level structures. This lesson takes the next logical step by exploring nested loops—loops that run inside other loops. Our goal is to master the skill of tracing their execution on paper. This is a crucial technique for understanding complex program behavior, debugging tricky logic, and, as you'll soon see, analyzing the efficiency of algorithms.
1. Understanding Nested Loops
A nested loop is simply a loop placed inside the body of another loop. We refer to them as the outer loop and the inner loop.
The fundamental rule of nested loops is: For each single iteration of the outer loop, the inner loop will execute all of its iterations from start to finish.
You can think of it like the hands of an analog clock: for every one time the hour hand moves forward, the minute hand completes an entire 60-minute cycle.
Let's watch a video that introduces this concept by showing a problem that is difficult to solve with a single loop, and then demonstrates how a nested loop provides an elegant solution.
C_43 Need of Nested Loops in C | Nested For loop in C
The video "Need of Nested Loops in C" from Jenny's Lectures CS IT provides an excellent step-by-step walkthrough.
Please watch the following segments: The concept: The instructor first demonstrates printing a single line of stars with one loop, then introduces the problem of printing a grid of stars, which leads to the need for a nested loop. Detailed trace: This is a critical section. Follow along as the instructor manually traces the execution, showing how the i (outer) and j (inner) variables change and how the inner loop fully resets and re-runs for each step of the outer loop. Flowchart visualization: This part presents a flowchart that visually maps the execution path, reinforcing the control flow you just traced.
The key takeaway is that the total number of times the innermost statement runs is the product of the number of iterations of the outer and inner loops. In the video's example, the outer loop ran 6 times and the inner loop ran 5 times for each of those, so the printf statement for the star was executed a total of 6 * 5 = 30 times.
2. The Trace Table: A Tool for Manual Execution
The verbal trace in the video is great for understanding, but for more complex code, we need a more structured method. This is where a trace table comes in. A trace table is a simple but powerful tool for "dry running" an algorithm on paper. You create columns for each variable in your program (and often a column for output) and meticulously fill in the values as they change, line by line.
This technique forces you to simulate what the computer is doing at every step, leaving no room for assumptions and often revealing logical errors.
Dry running algorithms with trace tables
The video "Dry running algorithms with trace tables" from Mr Dimmick's Computing Channel clearly explains this method.
Please watch these two parts: What is a trace table?: This introduces the concept and its purpose. Nested loop example: This provides a detailed demonstration of filling out a trace table for a nested for loop, showing exactly how to track the variables as the inner loop completes its cycles.
As you saw, the process is systematic:
- Set up a table with a column for each variable and for any output.
- Initialize the variables as specified in the code.
- Step through the outer loop. When it starts an iteration, update its loop variable in the table.
- Execute the inner loop from its beginning to its end, creating a new row in the trace table for each change in a variable's value.
- Once the inner loop completes, continue to the next iteration of the outer loop and repeat the process.
For a quick reference and another example, this article from TutorialsPoint is very helpful.
This article provides a concise textual explanation of nested loops and their execution flow.
Focus on the sections "Nested For Loops" and its subsection "Explanation of Nested Loop". This gives you a written step-by-step breakdown that complements the videos.
3. Practice: Trace the Output
Now it's your turn to apply this technique. Let's start with a C code snippet. Your task is to create a trace table on paper and predict the final output.
Here is the code:
#include <stdio.h>
int main() {
int x, y;
for (x = 10; x < 30; x = x + 5) {
for (y = x; y > 4; y = y / 2) {
printf("x: %d, y: %d\n", x, y);
}
}
return 0;
}
Instructions:
- Create a trace table with columns for
x,y, andOutput. - Start with the outer loop:
xis initialized to10. - Enter the inner loop:
yis initialized to the value ofx. - Trace the inner loop until its condition (
y > 4) becomes false. Record the output for each iteration. - Move to the next iteration of the outer loop (
xbecomes15) and repeat. - Continue until the outer loop's condition (
x < 30) is false.
Once you have your predicted output, compare it with the solution below.
Click to see the traced output

Here is a possible trace table that leads to this output:
x |
x < 30? |
y |
y > 4? |
Output | Notes |
|---|---|---|---|---|---|
10 |
True | Outer loop begins | |||
10 |
True | x: 10, y: 10 |
Inner loop, 1st iteration | ||
5 |
True | x: 10, y: 5 |
Inner loop, 2nd iteration | ||
2 |
False | Inner loop ends | |||
15 |
True | Outer loop, next iteration | |||
15 |
True | x: 15, y: 15 |
Inner loop, 1st iteration | ||
7 |
True | x: 15, y: 7 |
Inner loop, 2nd iteration | ||
3 |
False | Inner loop ends | |||
20 |
True | Outer loop, next iteration | |||
20 |
True | x: 20, y: 20 |
Inner loop, 1st iteration | ||
10 |
True | x: 20, y: 10 |
Inner loop, 2nd iteration | ||
5 |
True | x: 20, y: 5 |
Inner loop, 3rd iteration | ||
2 |
False | Inner loop ends | |||
25 |
True | Outer loop, next iteration | |||
25 |
True | x: 25, y: 25 |
Inner loop, 1st iteration | ||
12 |
True | x: 25, y: 12 |
Inner loop, 2nd iteration | ||
6 |
True | x: 25, y: 6 |
Inner loop, 3rd iteration | ||
3 |
False | Inner loop ends | |||
30 |
False | Outer loop ends |
4. Your Turn: Complete the Trace Table
Let's do one more, this time focusing on how variables are modified inside the loops.
Consider the following code snippet. Your task is to fill in the provided trace table to find the final value of the crazySum variable.
Take your time and fill out the table row by row on a piece of paper. What is the final value of crazySum?
Click to see the completed trace table and solution
The final value of crazySum is 42.
Here is the completed trace table:
first |
second |
crazySum |
|---|---|---|
| - | - | 0 |
| 1 | - | 1 |
| 0 | 1 | |
| 1 | 2 | |
| 2 | 4 | |
| 3 | 7 | |
| 2 | - | 9 |
| 0 | 9 | |
| 1 | 10 | |
| 2 | 12 | |
| 3 | 15 | |
| 3 | - | 18 |
| 0 | 18 | |
| 1 | 19 | |
| 2 | 21 | |
| 3 | 24 | |
| 4 | - | 28 |
| 0 | 28 | |
| 1 | 29 | |
| 2 | 31 | |
| 3 | 34 | |
| 5 | - | 39 |
| 0 | 39 | |
| 1 | 40 | |
| 2 | 42 | |
| 3 | 45 |
Wait, my final value is 45. Let's re-check the first <= 5 and second <= first conditions.
Ah, the outer loop should run for first = 5.crazySum becomes 34 + 5 = 39.
second = 0:crazySumremains39.second = 1:crazySumbecomes39 + 1 = 40.second = 2:crazySumbecomes40 + 2 = 42.second = 3:crazySumbecomes42 + 3 = 45.second = 4:crazySumbecomes45 + 4 = 49.second = 5:crazySumbecomes49 + 5 = 54.
Let me re-trace carefully.
crazySum= 0first= 1.first <= 5is true.crazySum= 0 + 1 = 1.second= 0.0 <= 1true.crazySum= 1 + 0 = 1.second= 1.1 <= 1true.crazySum= 1 + 1 = 2.second= 2.2 <= 1false.
first= 2.first <= 5is true.crazySum= 2 + 2 = 4.second= 0.0 <= 2true.crazySum= 4 + 0 = 4.second= 1.1 <= 2true.crazySum= 4 + 1 = 5.second= 2.2 <= 2true.crazySum= 5 + 2 = 7.second= 3.3 <= 2false.
first= 3.first <= 5is true.crazySum= 7 + 3 = 10.second= 0..3:crazySumbecomes 10, 11, 13, 16.
first= 4.first <= 5is true.crazySum= 16 + 4 = 20.second= 0..4:crazySumbecomes 20, 21, 23, 26, 30.
first= 5.first <= 5is true.crazySum= 30 + 5 = 35.second= 0..5:crazySumbecomes 35, 36, 38, 41, 45, 50.
first= 6.first <= 5is false. Loop terminates.
Final value of crazySum is 50.
The provided solution in the image seems to have a bug or follow a different logic. Let's carefully re-examine the image code. second <= 3 is the inner loop condition, not second <= first. This changes everything. Let's re-trace with the correct condition.
first |
second |
crazySum |
Notes |
|---|---|---|---|
| - | - | 0 | Initial value |
| 1 | - | 1 | crazySum = 0 + 1 |
| 0 | 1 | crazySum = 1 + 0 |
|
| 1 | 2 | crazySum = 1 + 1 |
|
| 2 | 4 | crazySum = 2 + 2 |
|
| 3 | 7 | crazySum = 4 + 3 |
|
| 2 | - | 9 | crazySum = 7 + 2 |
| 0 | 9 | crazySum = 9 + 0 |
|
| 1 | 10 | crazySum = 9 + 1 |
|
| 2 | 12 | crazySum = 10 + 2 |
|
| 3 | 15 | crazySum = 12 + 3 |
|
| 3 | - | 18 | crazySum = 15 + 3 |
| 0 | 18 | crazySum = 18 + 0 |
|
| 1 | 19 | crazySum = 18 + 1 |
|
| 2 | 21 | crazySum = 19 + 2 |
|
| 3 | 24 | crazySum = 21 + 3 |
|
| 4 | - | 28 | crazySum = 24 + 4 |
| 0 | 28 | crazySum = 28 + 0 |
|
| 1 | 29 | crazySum = 28 + 1 |
|
| 2 | 31 | crazySum = 29 + 2 |
|
| 3 | 34 | crazySum = 31 + 3 |
|
| 5 | - | 39 | crazySum = 34 + 5 |
| 0 | 39 | crazySum = 39 + 0 |
|
| 1 | 40 | crazySum = 39 + 1 |
|
| 2 | 42 | crazySum = 40 + 2 |
|
| 3 | 45 | crazySum = 42 + 3 |
|
first becomes 6, outer loop terminates. |
The final value of crazySum is 45.
This is a great example of how easy it is to make a mistake if you don't trace carefully!
Conclusion
In this lesson, you've learned one of the most fundamental skills for a programmer: how to manually trace code execution. This ability to "play computer" is invaluable for understanding how your programs work, for finding bugs, and for the topics we'll cover next.
Key Takeaways:
- A nested loop consists of an outer loop and an inner loop.
- The inner loop runs to completion for every single iteration of the outer loop.
- A trace table is a systematic way to track variable values and program output, step-by-step.
- The process is meticulous: follow the control flow line by line, update your table for every change, and don't make assumptions.
This lesson concludes our module on controlling program flow. You now have a solid command of conditional statements (if, switch) and looping constructs (while, for, nested loops), as well as statements to fine-tune their behavior (break, continue).
Preview of the Next Lesson: We are about to transition from the fundamentals of C programming to the core of this course: algorithms. Our next module, "Introduction to Algorithm Analysis," will start by asking a critical question: how do we measure if a program is "fast" or "slow"? Your new skill of tracing nested loops will be immediately useful, as counting the number of times the inner loop runs is the first step toward analyzing an algorithm's efficiency.