Loops in C: for, while, do-while & Nested Loops
Loops in C: for, while, do-while, Nested & Control Statements
Loops are fundamental control flow structures in C that allow repeated execution of a block of code as long as a specified condition is satisfied. They eliminate code duplication, enable iteration over data structures, and form the backbone of many algorithms. Mastering loops is essential for writing efficient and concise programs.
This tutorial provides an in-depth exploration of loops in C: for, while, do-while, nested loops, infinite loops, and loop control statements (break, continue, goto). It covers syntax, practical examples, common pitfalls, and best practices.
Conceptual Introduction & Fundamentals
What are Loops?
A loop is a programming construct that repeatedly executes a block of statements until a termination condition is met. Each repetition is called an iteration.
Without loops (repetitive code):
c
printf("Hello\n"); printf("Hello\n"); printf("Hello\n"); With loops (concise):
c
for (int i = 0; i < 3; i++) { printf("Hello\n"); } Why Use Loops?
- Reduce code duplication: Write once, execute many times.
- Handle variable repetition: The number of iterations can be determined at runtime.
- Process data structures: Iterate over arrays, strings, linked lists, etc.
- Implement algorithms: Searching, sorting, mathematical computations.
- Maintainability: Changes to the loop body apply to all iterations.
Types of Loops in C
| Loop | Type | When to Use |
|---|---|---|
for | Entry-controlled | When the number of iterations is known in advance |
while | Entry-controlled | When the number of iterations is unknown; condition checked before body |
do-while | Exit-controlled | When the body must execute at least once |
Loop Control Statements
| Statement | Purpose |
|---|---|
break | Terminates the loop immediately |
continue | Skips the rest of the current iteration, jumps to next iteration |
goto | Transfers control to a labeled statement (use sparingly) |
Syntax & Core Mechanics
1. for Loop
The for loop is an entry-controlled loop with three components: initialization, condition, and update.
Syntax:
c
for (initialization; condition; update) { // Body of loop } Components:
- Initialization: Executes once before the loop starts.
- Condition: Checked before each iteration; if false, loop exits.
- Update: Executes after each iteration.
Example:
c
#include <stdio.h> int main(void) { // Print numbers 1 to 5 for (int i = 0; i < 5; i++) { printf("%d ", i + 1); } printf("\n"); return 0; } Expected output:
text
1 2 3 4 5
Variations:
c
// Multiple variables for (int i = 0, j = 10; i < j; i++, j--) { printf("%d %d\n", i, j); } // Omitting components int i = 0; for (; i < 5; i++) { printf("%d ", i); } // Infinite for loop for (;;) { printf("Infinite\n"); break; // Prevent infinite } 2. while Loop
The while loop is an entry-controlled loop that repeats while the condition is true.
Syntax:
c
while (condition) { // Body of loop } Initialization and update are done separately.
Example:
c
#include <stdio.h> int main(void) { int i = 0; // Initialization while (i < 5) { // Condition printf("%d ", i + 1); i++; // Update } printf("\n"); return 0; } Expected output:
text
1 2 3 4 5
3. do-while Loop
The do-while loop is an exit-controlled loop that executes the body at least once before checking the condition.
Syntax:
c
do { // Body of loop } while (condition); Example:
c
#include <stdio.h> int main(void) { int i = 0; do { printf("%d ", i); i++; } while (i < 5); printf("\n"); return 0; } Expected output:
text
0 1 2 3 4
Key difference: The body executes at least once even if the condition is initially false.
c
int i = 10; do { printf("This prints once\n"); } while (i < 5); // Condition false, but body already executed 4. Nested Loops
A loop inside another loop. The inner loop runs completely for each iteration of the outer loop.
Example:
c
#include <stdio.h> int main(void) { // Outer loop runs 3 times for (int i = 0; i < 3; i++) { // Inner loop runs 2 times for each outer iteration for (int j = 0; j < 2; j++) { printf("i = %d, j = %d\n", i, j); } } return 0; } Expected output:
text
i = 0, j = 0 i = 0, j = 1 i = 1, j = 0 i = 1, j = 1 i = 2, j = 0 i = 2, j = 1
Common use: Processing 2D arrays, generating patterns, matrix operations.
5. Infinite Loops
An infinite loop runs forever because its condition never becomes false.
Using for:
c
for (;;) { printf("This loop will run forever.\n"); // Must have a break condition to exit } Using while:
c
while (1) { printf("This loop will run forever.\n"); } Using do-while:
c
do { printf("This loop will run forever.\n"); } while (1); Note: Infinite loops are useful for servers, event loops, and real-time systems but must have an exit mechanism (e.g., break on condition).
6. Loop Control Statements
break
Terminates the loop immediately and transfers control to the statement after the loop.
c
#include <stdio.h> int main(void) { for (int i = 0; i < 5; i++) { if (i == 3) { break; // Exit loop when i equals 3 } printf("%d ", i); } printf("\n"); return 0; } Expected output:
text
0 1 2
continue
Skips the rest of the current iteration and jumps to the next iteration.
c
#include <stdio.h> int main(void) { for (int i = 0; i < 5; i++) { if (i == 3) { continue; // Skip when i equals 3 } printf("%d ", i); } printf("\n"); return 0; } Expected output:
text
0 1 2 4
goto
Transfers control to a labeled statement. Use sparingly.
c
#include <stdio.h> int main(void) { for (int i = 0; i < 5; i++) { if (i == 3) { goto skip; // Jump to label } printf("%d ", i); } skip: printf("\nJumped to 'skip' label\n"); return 0; } Expected output:
text
0 1 2 Jumped to 'skip' label
Full Practical Code Example with Explanation
This program demonstrates all loop types and control statements in a realistic scenario: a number analysis tool that reads numbers, calculates statistics, and searches for specific values.
Program: Number Analysis Tool
c
/** * number_analysis.c * Demonstrates for, while, do-while, nested loops, break, continue, and goto. * Analyzes a list of numbers: finds min, max, average, and searches for a value. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <stdbool.h> #define MAX_NUMBERS 100 #define MAX_LINE_LEN 100 /* Function prototypes */ int readInteger(const char *prompt, int *outValue); void demonstrateForLoop(int numbers[], int count); void demonstrateWhileLoop(int numbers[], int count); void demonstrateDoWhileLoop(int numbers[], int count); void demonstrateNestedLoops(int numbers[], int count); void demonstrateBreakContinue(int numbers[], int count); int main(void) { int numbers[MAX_NUMBERS]; int count = 0; int choice; char buffer[MAX_LINE_LEN]; printf("=== Number Analysis Tool ===\n"); /* Read numbers using while loop */ printf("Enter numbers (enter -1 to stop):\n"); while (count < MAX_NUMBERS) { int value; if (readInteger("", &value) != 0) { fprintf(stderr, "Invalid input.\n"); continue; } if (value == -1) { break; // Exit loop when user enters -1 } numbers[count++] = value; } if (count == 0) { printf("No numbers entered.\n"); return EXIT_SUCCESS; } printf("You entered %d numbers.\n", count); /* Menu-driven demonstration */ while (1) { printf("\n--- Analysis Menu ---\n"); printf("1. Display numbers (for loop)\n"); printf("2. Calculate sum and average (while loop)\n"); printf("3. Find minimum (do-while loop)\n"); printf("4. Display multiplication table (nested loops)\n"); printf("5. Demonstrate break and continue\n"); printf("6. Exit\n"); printf("Enter choice: "); fflush(stdout); if (fgets(buffer, sizeof(buffer), stdin) == NULL) { fprintf(stderr, "Error reading choice.\n"); return EXIT_FAILURE; } choice = atoi(buffer); switch (choice) { case 1: demonstrateForLoop(numbers, count); break; case 2: demonstrateWhileLoop(numbers, count); break; case 3: demonstrateDoWhileLoop(numbers, count); break; case 4: demonstrateNestedLoops(numbers, count); break; case 5: demonstrateBreakContinue(numbers, count); break; case 6: printf("Exiting.\n"); return EXIT_SUCCESS; default: printf("Invalid choice. Please try again.\n"); break; } } return EXIT_SUCCESS; } /* Demonstrates for loop to display numbers */ void demonstrateForLoop(int numbers[], int count) { printf("\n=== Numbers (for loop) ===\n"); for (int i = 0; i < count; i++) { printf("%d ", numbers[i]); } printf("\n"); } /* Demonstrates while loop for sum and average */ void demonstrateWhileLoop(int numbers[], int count) { printf("\n=== Sum and Average (while loop) ===\n"); int sum = 0; int i = 0; while (i < count) { sum += numbers[i]; i++; } double average = (double)sum / count; printf("Sum: %d\n", sum); printf("Average: %.2f\n", average); } /* Demonstrates do-while loop to find minimum */ void demonstrateDoWhileLoop(int numbers[], int count) { printf("\n=== Minimum (do-while loop) ===\n"); int min = numbers[0]; int i = 1; do { if (numbers[i] < min) { min = numbers[i]; } i++; } while (i < count); printf("Minimum: %d\n", min); } /* Demonstrates nested loops for multiplication table */ void demonstrateNestedLoops(int numbers[], int count) { printf("\n=== Multiplication Table (nested loops) ===\n"); int firstNumber = numbers[0]; // Outer loop: rows (1 to firstNumber) for (int i = 1; i <= firstNumber; i++) { // Inner loop: columns (1 to 10) for (int j = 1; j <= 10; j++) { printf("%3d ", i * j); } printf("\n"); } } /* Demonstrates break and continue */ void demonstrateBreakContinue(int numbers[], int count) { printf("\n=== Break and Continue ===\n"); // Break: stop at first negative number printf("Break at first negative number:\n"); for (int i = 0; i < count; i++) { if (numbers[i] < 0) { break; } printf("%d ", numbers[i]); } printf("\n"); // Continue: skip negative numbers printf("Continue (skip negatives):\n"); for (int i = 0; i < count; i++) { if (numbers[i] < 0) { continue; } printf("%d ", numbers[i]); } printf("\n"); // Goto: jump to label printf("Goto demonstration:\n"); for (int i = 0; i < count; i++) { if (numbers[i] == 100) { goto found_hundred; } printf("%d ", numbers[i]); } printf("\n100 not found.\n"); return; found_hundred: printf("\nFound 100 in the list!\n"); } /* Reads an integer safely using fgets and strtol */ int readInteger(const char *prompt, int *outValue) { char buffer[MAX_LINE_LEN]; char *endPtr; long val; if (prompt[0] != '\0') { printf("%s", prompt); fflush(stdout); } if (fgets(buffer, sizeof(buffer), stdin) == NULL) { return -1; } errno = 0; val = strtol(buffer, &endPtr, 10); if (endPtr == buffer || (*endPtr != '\n' && *endPtr != '\0')) { return -1; } if (errno == ERANGE || val < -2147483647 - 1 || val > 2147483647) { return -1; } *outValue = (int)val; return 0; } Explanation of Loop Usage
whileloop: Reads numbers until-1is entered orMAX_NUMBERSis reached.forloop: Displays all numbers.whileloop: Calculates sum and average.do-whileloop: Finds minimum (ensures at least one iteration).- Nested
forloops: Displays multiplication table. break: Stops at first negative number.continue: Skips negative numbers.goto: Jumps to label when 100 is found.
Expected Output (sample run)
text
=== Number Analysis Tool === Enter numbers (enter -1 to stop): 5 10 15 -1 You entered 3 numbers. --- Analysis Menu --- 1. Display numbers (for loop) 2. Calculate sum and average (while loop) 3. Find minimum (do-while loop) 4. Display multiplication table (nested loops) 5. Demonstrate break and continue 6. Exit Enter choice: 1 === Numbers (for loop) === 5 10 15 Enter choice: 2 === Sum and Average (while loop) === Sum: 30 Average: 10.00 Enter choice: 3 === Minimum (do-while loop) === Minimum: 5 Enter choice: 4 === Multiplication Table (nested loops) === 1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 Enter choice: 5 === Break and Continue === Break at first negative number: 5 10 15 Continue (skip negatives): 5 10 15 Goto demonstration: 5 10 15 100 not found. Enter choice: 6 Exiting.
Common Pitfalls, Edge Cases & Memory Considerations
1. Off-by-One Errors
Loop boundaries are often wrong by one iteration.
c
for (int i = 0; i <= 5; i++) { // Runs 6 times (0 to 5) } for (int i = 0; i < 5; i++) { // Runs 5 times (0 to 4) } Solution: Carefully check loop conditions and test with small values.
2. Infinite Loops
Forgetting to update the loop variable or incorrect condition can cause infinite loops.
c
int i = 0; while (i < 5) { printf("%d ", i); // Missing i++ -> infinite loop } Solution: Ensure the loop variable is updated and the condition will eventually become false.
3. Semicolon After Loop Condition
A semicolon immediately after the loop condition creates an empty loop body.
c
for (int i = 0; i < 5; i++); { // Empty loop body; block executes once printf("%d ", i); // i is out of scope or garbage } Solution: Remove the semicolon or use it intentionally for empty loops.
4. Using = Instead of ==
Assignment in a loop condition can cause unexpected behavior.
c
while (x = 5) { // Always true; assigns 5 to x } Solution: Use == for comparison. Enable compiler warnings.
5. Modifying Loop Variable Inside Body
Changing the loop variable inside the body can lead to unpredictable behavior.
c
for (int i = 0; i < 5; i++) { i += 2; // Skips iterations unexpectedly } Solution: Avoid modifying the loop variable inside the body unless intentional.
6. Integer Overflow in Loop Counter
If the loop variable overflows, the loop may become infinite or terminate incorrectly.
c
for (int i = 0; i < INT_MAX; i++) { // i++ overflows at INT_MAX } Solution: Use long long for very large counts, or check for overflow.
7. break and continue in Nested Loops
break and continue only affect the innermost loop. To break out of multiple nested loops, use goto or flags.
c
for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { if (j == 3) { break; // Only breaks inner loop } } } Solution: Use goto for breaking out of nested loops, or use a flag variable.
8. Off-by-One in Array Access
Looping beyond array bounds causes undefined behavior.
c
int arr[5]; for (int i = 0; i <= 5; i++) { // Accesses arr[5], out of bounds arr[i] = i; } Solution: Always loop i < array_size.
9. Uninitialized Loop Variable
Using an uninitialized loop variable is undefined behavior.
c
int i; while (i < 5) { // i is garbage printf("%d ", i); i++; } Solution: Initialize loop variables: int i = 0;.
10. Memory Considerations
- Loops do not allocate memory inherently.
- Large arrays declared inside loops are reallocated each iteration (stack overhead).
- Use
mallocfor large dynamic allocations outside the loop, then reuse.
c
// Inefficient: allocates each iteration for (int i = 0; i < 1000; i++) { int temp[10000]; // Stack allocation each iteration } // Efficient: allocate once int temp[10000]; for (int i = 0; i < 1000; i++) { // use temp } Summary & Best Practices
Loops are essential for repetitive tasks in C. Understanding the different loop types, their appropriate use cases, and control statements is crucial for writing efficient and correct code.
Key Takeaways
forloop: Use when the number of iterations is known.whileloop: Use when the condition must be checked before each iteration.do-whileloop: Use when the body must execute at least once.- Nested loops: One loop inside another; inner runs completely for each outer iteration.
break: Exits the loop immediately.continue: Skips to the next iteration.goto: Transfers control to a labeled statement (use sparingly).
Best Practices
- Use
forloops when the number of iterations is known. - Use
whileloops when the loop depends on a condition that may change. - Use
do-whilewhen at least one execution is required. - Always initialize loop variables before use.
- Keep loop bodies short and focused; extract complex logic into functions.
- Avoid side effects in loop conditions.
- Use braces
{}consistently for loop bodies, even single statements. - Limit nesting depth (3-4 levels max) for readability.
- Use
breakandcontinuesparingly; overuse can make code hard to follow. - Test edge cases: zero iterations, one iteration, maximum iterations.
By mastering loops in C, you’ll write programs that efficiently handle repetition, process data structures, and implement complex algorithms with clarity.



