For Loop in C
The for
statement is one of the main flow control statements in C. It allows the creation of iterative loops of instructions.
The syntax of the for
statement includes three parts: the initialization expression, the control expression that determines the continuation of the loop, and the end-of-iteration operation.
The for
statement is particularly useful when you want to execute a block of code a known number of times. However, the for
statement is so flexible that it can be used to construct virtually any kind of loop.
In this lesson, we will examine in detail the syntax and usage of the for
statement to implement loops.
- The
for
statement allows you to create loops by specifying three expressions: the initialization expression, the control expression, and the end-of-iteration operation; - Although the
for
statement is commonly used to execute statements a known number of times, its flexibility allows it to construct any type of loop; - The three expressions are not mandatory;
- By using the comma operator, multiple expressions can be combined.
for
Statement
The for
statement is the most versatile—but also the most complex—looping construct in the C language. Its ideal use case is when there is a counting variable, but it can also be used for many other types of loops.
The for
statement has the form:
for ( expression_1 ; expression_2 ; expression_3 ) statement;
To understand the purpose of the three expressions in the for
statement, let’s revisit the countdown example that we already analyzed in the lessons on while loops and do while loops.
We want to print a countdown starting from 10. We can implement this functionality using a for
loop as follows:
int n;
for (n = 10; n > 0; --n) {
printf("%d\n", n);
}
printf("Liftoff!\n");
This for
loop, in practice, performs the following steps:
- Initializes the variable
n
to 10 using the first expressionn = 10
; - Checks whether the variable
n
is greater than zero using the second expressionn > 0
; - Since the condition is true, it executes the body of the loop;
- After the body is executed, it modifies the variable
n
using the third expression--n
; - It then re-evaluates the condition expressed by the second expression
n > 0
; - If the condition is still true, it executes the loop body again; otherwise, it exits the loop.
Therefore, the for
loop is closely related to a while
loop—so much so that any for
loop can always be rewritten as a while
loop.
In practice, a for
statement of this type:
for ( expression_1 ; expression_2 ; expression_3 ) statement;
is equivalent to a while
loop written as:
expression_1;
while (expression_2) {
statement;
expression_3;
}
From this structure, we can identify the purpose of the three expressions:
expression_1
is the initialization expression: it is executed once before the loop starts;expression_2
is the control expression: it determines whether the loop continues. If true, the loop proceeds; otherwise, it ends;expression_3
is the end-of-iteration operation: it is executed at the end of each iteration, after the loop body.
Using this scheme, we can rewrite the example code as follows:
/* For loop format */
int n;
for (n = 10; n > 0; --n) {
printf("%d\n", n);
}
printf("Liftoff!\n");
/* Equivalent while loop format */
int n;
n = 10;
while (n > 0) {
printf("%d\n", n);
--n;
}
printf("Liftoff!\n");
In general, the structure of a for
loop with its three expressions follows this flowchart:
Since the initialization expression and the end-of-iteration operation are executed as statements, their return values are irrelevant. What matters is the effect they have. Typically, these expressions involve assignment, increment, or decrement operations.
for
Statement
The for
statement in the C language allows the implementation of iterative loops.
The general syntax is:
for ( init_expr; control_expr; end_expr ) statement;
The three expressions that appear in a for
statement are:
init_expr
: the initialization expression, executed before the loop begins;control_expr
: the control expression, evaluated at the start of each iteration. If it evaluates to true, the loop body is executed; otherwise, the loop ends;end_expr
: the end-of-iteration expression, executed at the end of each iteration after the loop body but before checking the control expression again.
Typical for
Loops
The for
loop is often the ideal choice for loops that count, meaning those that increment or decrement a variable. A for
statement that counts a number of times equal to n
typically takes one of the following common forms:
-
Counting from
0
ton - 1
:for (i = 0; i < n; ++i)
-
Counting from
1
ton
:for (i = 1; i <= n; ++i)
-
Counting backward from
n - 1
to0
:for (i = n - 1; i >= 0; --i)
-
Counting backward from
n
to1
:for (i = n; i > 0; --i)
The four patterns listed above are among the most common when programming in C. Using them helps avoid typical mistakes:
- Using
<
instead of>
and vice versa in the control expression. Note that when counting up, we used<
or<=
. Conversely, when counting down, we used>
or>=
. - Using the equality operator
==
in the control expression. This is often a mistake, because at the start of afor
loop—as with awhile
loop—the control expression must evaluate to true. It becomes false to end the loop. So a control expression likei == n
doesn't make much sense, because it wouldn’t be true at the beginning. - Off-by-one errors. These occur when you count one item too many and typically happen in
for
loops when the control expression is incorrect. For example, usingi <= n
instead ofi < n
.
Omitting Expressions in a for
Loop
The for
loop is very flexible. In fact, the three expressions in the for
statement are not required.
There may be cases where not all three expressions are needed, and in C, it’s perfectly valid to omit one or even all of them.
If we omit the first expression, the for
loop does not perform any initialization at the start. For example, going back to the countdown, we can rewrite the code without the first expression like this:
int n;
n = 10;
for (; n > 0; --n) {
printf("%d\n", n);
}
printf("Liftoff!\n");
In this case, we performed the initialization of the variable n
separately, so the first expression isn’t necessary. Note, however, that the semicolon must remain even if the expression is omitted.
If the third expression is omitted, the for
loop does not perform any end-of-iteration operation. At this point, it becomes the responsibility of the loop body to ensure the control expression eventually becomes false.
Again using the countdown example, we can omit the third expression like this:
int n;
for (n = 10; n > 0;) {
printf("%d\n", n);
--n;
}
printf("Liftoff!\n");
We omitted the third expression but had to include the line --n
. Without this line, the variable n
would never be decremented, and the control expression would never become false.
Combining both of the above, if we omit both the first and third expressions, the for
loop essentially becomes a while
loop in another form.
Returning to the countdown example again, we can rewrite the for
loop omitting both the first and third expressions as follows:
int n;
n = 10;
for (; n > 0;) {
printf("%d\n", n);
--n;
}
printf("Liftoff!\n");
But the code above is identical to the following while
loop:
int n = 0;
n = 10;
while (n > 0) {
printf("%d\n", n);
--n;
}
printf("Liftoff!\n");
In these cases, however, the while
loop is more readable and clearer, so it's generally preferable to use while
.
Finally, if we omit the second expression, it is considered true by default. In this case, the for
loop never terminates unless exited in some other way, as we’ll see in the next lessons. For example, it’s possible to create an infinite loop like this:
for (;;) {
/* Infinite loop */
/* ... */
}
for
Statement and C99
In the C language, according to the C89 standard, variables must be declared at the beginning. Strictly speaking, in C89, variables must be declared at the beginning of the scope. In upcoming lessons, we’ll learn what a variable’s scope is. For now, it’s enough to know that in C89 a variable must be declared before any statement.
Based on this, if we take the countdown example, we must write the program like this:
1 2 3 4 5 6 7 8 9 10 |
|
In other words, we had to declare the variable n
first on line 4.
Starting from the C99 standard, however, variables can be declared anywhere. So if we are using a C99 compiler (and nearly all modern compilers support the C99 standard), we can replace the first expression in a for
loop with a declaration.
So we can rewrite the code above as follows:
1 2 3 4 5 6 7 8 9 10 |
|
This way, the variable n
is declared directly within the for
loop, and there's no need to declare it beforehand. However, this also means that the variable n
is not accessible outside the for
loop. This is a preview of the visibility rules that we will study later.
Declaring the control variable of a for
loop within the loop itself is always a good idea. As always, it improves program readability. However, if you need to access the control variable outside the loop, especially after it ends, you must use the older form of the for
loop.
Comma Operator
The flexibility of the for
loop in C also lies in the ability to use multiple expressions by employing the comma operator.
For example, it’s possible to write a for
loop that initializes more than one variable or modifies multiple variables in each iteration.
To do this, the comma operator is used in the following form:
expression_1 , expression_2
Using the comma operator creates a new expression with its own result. The comma operator is evaluated in two steps:
- The first expression,
expression_1
, is evaluated, and its result is discarded; - The second expression,
expression_2
, is then evaluated, and its result becomes the result of the entire expression.
For example, we can write the following lines of code:
int x;
x = (5 * 6, 7 + 8);
At this point, the program first evaluates the expression 5 * 6
, and its result, 30
, is discarded. Then it evaluates the expression 7 + 8
, and its result, 15
, becomes the result of the entire expression and, consequently, the new value of the variable x
.
The comma operator has a lower precedence than all other operators, which is why, in the previous example, we had to enclose the expression in parentheses. In fact, if we had written the following code:
x = 5 * 6, 7 + 8;
The variable x
would end up with the value 30
, because the assignment has higher precedence than the comma operator.
The comma operator is also left-associative. Therefore, we can perform multiple assignments like this:
x = 1, y = 2, z = x + y;
In doing so, the compiler interprets the statement as follows:
((x = 1), (y = 2), (z = (x + y)));
So it proceeds like this:
- Assigns the value
1
to the variablex
; - Assigns the value
2
to the variabley
; - Evaluates the result of
x + y
, which is3
, and assigns it toz
.
The comma operator can be used in situations where only one expression is allowed but you want to include multiple expressions. The operator allows us to glue two or more expressions together into a single expression. Similarly, curly braces allow us to group multiple statements into a compound statement.
The need to group multiple expressions does not arise often. However, for
loops are the most common case where this is needed.
For example, suppose we want to write a program that calculates the sum of the first 10 natural numbers. We can write our program like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
In the program above, we initialized the variable s
on line 7 separately. We can use the comma operator and write:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Now, in line 7, using the comma operator, we initialized both variables. This makes the for
statement more flexible.
To summarize:
Comma Operator
The comma operator ,
is an operator that allows multiple expressions to be combined into a single expression. The comma operator has the following form:
expression_1, expression_2
The comma operator first evaluates expression_1
and discards its result. It then evaluates expression_2
, and its result becomes the result of the entire expression.
The comma operator has lower precedence than all other operators and is left-associative.
Summary
In this lesson, we studied the for
statement, which allows the implementation of loops in a flexible way.
We saw that the syntax of a for
statement includes three expressions:
- The initialization expression;
- The control expression;
- The end-of-iteration operation.
We also saw that none of these expressions are mandatory, and there are cases where they can be omitted. The flexibility of the for
statement lies precisely in this, as by playing with the three expressions it’s possible to implement loops entirely equivalent to while
loops.
Additionally, by using the comma operator, it is possible to create more complex expressions for building for
loops.
In the next lesson, we will learn how to exit a loop.