C For Loop

A for loop repeats a block of C code when the setup, stopping test, and update fit together in one clear pattern. It is the standard loop for counting, walking through arrays, repeating a known number of times, and building table-like output. Learning it well matters because many C programs spend most of their time doing the same operation across a sequence of values.

Overview: How It Works

A for loop is a pre-test loop, like while, but it places three important pieces of loop control in one header: initialization, condition, and update. The initialization runs once before the loop starts. The condition is checked before each possible iteration. If the condition is nonzero, the loop body runs. After the body finishes, the update expression runs, and then C checks the condition again.

This shape makes for especially useful for counting loops. A common pattern is for (int i = 0; i < length; i++). The variable i starts at 0, the loop continues while i is less than length, and i++ advances to the next index after each iteration. Because C arrays use zero-based indexing, this pattern visits every valid index from 0 through length - 1.

The loop header does not create special machine magic. It is mostly a compact way to express the same control flow you could write with a while loop. Local variables declared in the initialization part, such as int i = 0, have block scope tied to the loop statement. That means i is available in the condition, body, and update expression, but not after the loop ends. This keeps loop counters from leaking into later code.

The condition follows C’s normal truth rule: zero is false and any nonzero value is true. Most for conditions are comparisons such as i < 5, row < rows, or index >= 0. The update expression is often an increment or decrement, but it can also add by two, move backward, or update more than one variable with the comma operator. The important rule is that the loop must make progress toward a false condition unless it is intentionally infinite.

Syntax

for (initialization; condition; update) {
    statements;
}
Part Meaning
initialization Runs once before the first condition test. Often declares and initializes a counter.
condition Tested before each iteration. Zero stops the loop; nonzero enters the body.
update Runs after each completed body execution, before the next condition test.
{ statements; } The loop body. These statements run once for each true condition test.

The semicolons inside the header are required because they separate the three expressions. Any of the three parts may be omitted, but the semicolons remain. For beginners, the clearest form is usually the complete counting pattern with all three parts present.

Examples

Example 1: Count a Fixed Number of Times

#include <stdio.h>

int main(void)
{
    for (int count = 1; count <= 5; count++) {
        printf("Count: %d\n", count);
    }

    printf("Finished\n");

    return 0;
}

Output:

Count: 1
Count: 2
Count: 3
Count: 4
Count: 5
Finished

The counter starts at 1. Before each iteration, C checks whether count <= 5. The body prints the current value, and then count++ adds one. When count becomes 6, the condition is false and execution continues after the loop.

Example 2: Add Values in an Array

#include <stdio.h>

int main(void)
{
    int scores[] = {84, 90, 76, 88};
    int length = 4;
    int total = 0;

    for (int i = 0; i < length; i++) {
        total += scores[i];
    }

    printf("Total: %d\n", total);
    printf("Average: %.1f\n", (double) total / length);

    return 0;
}

Output:

Total: 338
Average: 84.5

This loop visits indexes 0, 1, 2, and 3, which are the valid positions in a four-element array. The condition uses i < length, not i <= length, because the last valid index is one less than the number of elements. The cast to double makes the average use floating-point division instead of integer division.

Example 3: Count Backward

#include <stdio.h>

int main(void)
{
    for (int seconds = 5; seconds >= 1; seconds--) {
        printf("%d\n", seconds);
    }

    printf("Launch\n");

    return 0;
}

Output:

5
4
3
2
1
Launch

A for loop does not have to count upward. Here the counter starts at 5, continues while it is at least 1, and decreases with seconds--. This pattern is useful for countdowns, reverse array traversal, and retry limits.

Example 4: Nested For Loops

#include <stdio.h>

int main(void)
{
    for (int row = 1; row <= 3; row++) {
        for (int col = 1; col <= 4; col++) {
            printf("%d,%d ", row, col);
        }
        printf("\n");
    }

    return 0;
}

Output:

1,1 1,2 1,3 1,4 
2,1 2,2 2,3 2,4 
3,1 3,2 3,3 3,4 

The outer loop controls rows, and the inner loop controls columns. For each one value of row, the inner col loop runs completely from 1 through 4. Nested loops are common for grids, multiplication tables, matrices, and any task where each item contains another sequence of items.

How It Works Step by Step

  1. C runs the initialization part once, before the first iteration.
  2. C evaluates the condition. If it is zero, the loop body is skipped.
  3. If the condition is nonzero, C runs the body statements in order.
  4. After the body finishes, C runs the update expression.
  5. C jumps back to the condition and tests again.
  6. The loop ends when the condition becomes zero, or when a statement such as break or return exits earlier.

For for (int i = 0; i < 3; i++), the visible values inside the body are 0, 1, and 2. The update still runs after printing 2, making i become 3. Then the condition 3 < 3 is false, so the body does not run again.

Common Mistakes

Off-by-One Errors

The most common array-loop bug is using <= when the loop should use <. If an array has length elements, its valid indexes are 0 through length - 1. A loop such as for (int i = 0; i <= length; i++) eventually tries to read array[length], which is outside the array. The corrected pattern is:

#include <stdio.h>

int main(void)
{
    int numbers[] = {2, 4, 6};
    int length = 3;

    for (int i = 0; i < length; i++) {
        printf("%d\n", numbers[i]);
    }

    return 0;
}

Output:

2
4
6

Adding a Semicolon After the Header

A semicolon immediately after for (...) creates an empty loop body. The following block is no longer controlled by the loop. Write for (...) { ... }, with no semicolon before the opening brace.

Changing the Counter Unexpectedly

A loop is hard to reason about when the counter is updated both in the header and in the body. For example, incrementing i inside a loop that already has i++ in the header can skip elements. If you need unusual movement, make the update rule explicit in one place.

Using an Unreachable Condition

The initialization, condition, and update must agree. A loop such as for (int i = 10; i < 5; i++) never runs because the condition is false before the first iteration. A loop such as for (int i = 0; i < 5; i--) moves away from the stopping point and can run forever.

Best Practices

  • Use for when initialization, condition, and update form one clear loop-control pattern.
  • Use i < length for zero-based array traversal, not i <= length.
  • Declare loop counters in the initialization part when they are only needed by that loop.
  • Keep the loop body focused. If it grows large, move a meaningful piece into a function.
  • Use braces around the body even when it has only one statement.
  • Avoid changing the counter inside the body unless the whole loop is designed around that behavior.
  • Choose descriptive counter names such as row and col for nested loops.
  • Use while instead when the loop is controlled mainly by input, a sentinel value, or an external condition.

Practice Exercises

  1. Write a program that uses a for loop to print the even numbers from 2 through 20.
  2. Create an array of five prices in cents. Use a for loop to calculate and print the total price.
  3. Write nested for loops that print a 5 by 5 multiplication table. Hint: the value at each position is row * col.

Summary

  • A for loop combines initialization, condition testing, and updating in one header.
  • The initialization runs once, the condition runs before each iteration, and the update runs after each completed body execution.
  • For arrays, the usual safe pattern is for (int i = 0; i < length; i++).
  • Loop counters declared in the header are scoped to the loop statement.
  • Off-by-one errors, accidental header semicolons, and mismatched update directions are common sources of bugs.
  • Nested for loops are useful when one sequence must be processed inside another sequence.