Code of the Day
BeginnerControl flow

for loops

Write counted loops in C with the for statement — understanding the three-part header, nested loops, and when to prefer for over while.

CBeginner10 min read
Recommended first
By the end of this lesson you will be able to:
  • Write a for loop with an initialiser, condition, and update
  • Trace the execution of a for loop step by step
  • Write nested for loops to process two-dimensional data
  • Distinguish when for is cleaner than while

The for loop is the most commonly used loop in C. It is not fundamentally more powerful than while — every for loop can be rewritten as a while loop — but it collects the three parts of a loop (initialise, check, update) into one header line, making counted iteration much easier to read.

Syntax

for (initialiser; condition; update) {
    /* body */
}

Equivalent while loop:

initialiser;
while (condition) {
    /* body */
    update;
}

Both forms are identical in behaviour. Use for when you know how many iterations you need before the loop starts. Use while when the number of iterations depends on something that happens inside the loop.

Counting up

#include <stdio.h>

int main(void) {
    for (int i = 0; i < 5; i++) {
        printf("i = %d\n", i);
    }
    return 0;
}

Output:

i = 0
i = 1
i = 2
i = 3
i = 4

Three things to note:

  • int i = 0 is the initialiser — it runs once before the loop starts.
  • i < 5 is the condition — tested before each iteration.
  • i++ is the update — runs after each iteration, before the condition is re-tested.
  • The loop variable i exists only inside the loop (C99 and later).

C arrays are zero-indexed: the first element is at index 0, the last at index n-1. You will see i < n (not i <= n-1) as the canonical pattern everywhere.

Counting down

for (int i = 10; i > 0; i--) {
    printf("%d ", i);
}
printf("\n");

Output: 10 9 8 7 6 5 4 3 2 1

Iterating over an array

#include <stdio.h>

int main(void) {
    int scores[] = {92, 78, 85, 91, 65};
    int n = 5;
    int total = 0;

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

    printf("Average: %.1f\n", (double)total / n);
    return 0;
}

This pattern — for (int i = 0; i < n; i++) iterating over array[i] — is the single most common loop in C.

Nested for loops

Nested loops let you iterate over two-dimensional structures like matrices:

#include <stdio.h>

int main(void) {
    for (int row = 1; row <= 3; row++) {
        for (int col = 1; col <= 3; col++) {
            printf("%d*%d=%-2d  ", row, col, row * col);
        }
        printf("\n");
    }
    return 0;
}

Output:

1*1=1   1*2=2   1*3=3   
2*1=2   2*2=4   2*3=6   
3*1=3   3*2=6   3*3=9   

The outer loop iterates through rows, the inner through columns. For each outer iteration, the inner loop completes fully.

The %-2d format specifier. The - means left-align the number, and 2 means use at least 2 characters. This keeps the multiplication table columns aligned even when single-digit numbers appear alongside double-digit ones.

Multiple variables in a for loop

The comma operator lets you put multiple statements in the initialiser or update:

for (int i = 0, j = 10; i < j; i++, j--) {
    printf("i=%d j=%d\n", i, j);
}

Both i and j are initialised in the header and both are updated. Use this sparingly — it is a valid pattern for two-pointer algorithms but can make loops harder to read.

Omitting parts of the header

Any of the three parts can be omitted:

int i = 0;
for (; i < 10; i++) { /* no initialiser -- i was already declared */ }

for (int i = 0; ; i++) { /* no condition -- infinite loop, like while(1) */ }

for (int i = 0; i < 10; ) { /* no update -- update inside the body */ }

Omitting the condition creates an infinite loop. All three omissions are valid C, but the common idiom for an intentional infinite loop is while (1), not for (;;) (though both are used and both are correct).

A practical example: prime check

#include <stdio.h>
#include <stdbool.h>

int main(void) {
    int n = 29;
    bool is_prime = (n > 1);

    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            is_prime = false;
            break;
        }
    }

    printf("%d is %s\n", n, is_prime ? "prime" : "not prime");
    return 0;
}

The loop runs up to sqrt(n) (written as i * i <= n to avoid floating-point). The break exits the loop early as soon as a factor is found — no point checking further.

Where to go next

Next: break, continue, and loop patterns — how to exit loops early, skip individual iterations, and recognise common loop idioms.

Finished reading? Mark it complete to track your progress.

On this page