for Loops

A for loop packs the three parts of a counting loop — start, condition and step — into one line. It's the everyday loop for going through a range of numbers or the elements of an array.

The three parts

C
#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 5; i++) {
        printf("%d squared is %d\n", i, i * i);
    }
    return 0;
}
Output
1 squared is 1
2 squared is 4
3 squared is 9
4 squared is 16
5 squared is 25
PartRuns
int i = 1Once, before the loop starts
i <= 5Before every pass; the loop stops when it's false
i++After every pass

A variable declared in the first part only exists inside the loop. Any part can be left empty; for (;;) loops forever.

Counting patterns

C
#include <stdio.h>

int main(void) {
    for (int i = 10; i > 0; i -= 3) printf("%d ", i);
    printf("\n");
    for (int i = 1; i <= 1000; i *= 10) printf("%d ", i);
    printf("\n");
    for (int i = 0, j = 10; i < j; i++, j--) printf("(%d,%d) ", i, j);
    printf("\n");
    return 0;
}
Output
10 7 4 1
1 10 100 1000
(0,10) (1,9) (2,8) (3,7) (4,6)

The comma operator lets you update two variables at once, as in the last loop.

Looping over an array

The standard idiom counts from 0 up to, but not including, the number of elements:

C
#include <stdio.h>

int main(void) {
    double prices[] = { 3.50, 12.00, 7.25, 1.99 };
    size_t count = sizeof prices / sizeof prices[0];
    double total = 0;
    for (size_t i = 0; i < count; i++) {
        total += prices[i];
    }
    printf("%zu items, total %.2f, average %.2f\n", count, total, total / count);
    return 0;
}
Output
4 items, total 24.74, average 6.18

sizeof prices / sizeof prices[0] computes the element count, so the loop stays correct if you add prices. Arrays are covered in lesson 26.

Nested loops

C
#include <stdio.h>

int main(void) {
    int height = 4;
    for (int row = 1; row <= height; row++) {
        for (int space = 0; space < height - row; space++) putchar(' ');
        for (int star = 0; star < 2 * row - 1; star++) putchar('*');
        putchar('\n');
    }
    return 0;
}
Output
   *
  ***
 *****
*******

The inner loop runs completely for each pass of the outer loop. putchar prints a single character.

Counting down with unsigned types

Because unsigned values can't go below zero, this classic loop never ends — i wraps from 0 to a huge number:

C
for (size_t i = count - 1; i >= 0; i--)   // i >= 0 is always true!

GCC warns about this with -Wextra ("comparison is always true"). A safe way to count down over an array:

C
#include <stdio.h>

int main(void) {
    int values[] = { 10, 20, 30 };
    size_t count = sizeof values / sizeof values[0];
    for (size_t i = count; i-- > 0; ) {
        printf("%d ", values[i]);
    }
    printf("\n");
    return 0;
}
Output
30 20 10

for or while?

Use for when there's a clear counter or range; use while when the loop continues until some condition changes. Any for loop can be written as a while loop — the for form just keeps the loop's bookkeeping in one place.

Try it yourself

Print the prime numbers below 50 by testing each number for divisors up to its square root.

Try it yourself · main.c
Edit the code, copy it into main.c, then compile and run it with cc -std=c17 -Wall main.c -o main && ./main. How to set up a C compiler
Output
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47