tl;dr– A for
loop is just a while
loop that has extra slots for a pre-loop statement and a post-loop-run statement. Since they're pretty much the same thing just written differently, a for
loop is best understood as syntactic sugar that's useful when it increases the readability of the code.
Sometimes new programmers are worried about performance, thinking that syntactic sugar might be less efficient. That's not the case; the compiler really doesn't care how you write these loops, it's all the same to it. So, students should be told to just write whichever's cleaner in the current context.
Homework/test question idea: Have students convert a for
loop into an equivalent while
loop, or a while
loop into an equivalent for
loop.
Mapping between for
and while
.
The for
loop:
for (prestatement; condition; poststatement)
{
// loop body
}
is equivalent to the while
loop:
{
prestatement;
while (condition)
{
// loop body
poststatement;
}
}
, where:
prestatement
is an executable statement that happens only once, before the loop starts.
- If omitted, then the loop just doesn't do anything extra before starting.
condition
is a Boolean
expression that's evaluated at the start of each loop execution, breaking if false
.
- If omitted, then there's no break check there.
poststatement
is an executable statement that happens after the end of each loop execution.
- If omitted, then the loop just doesn't do anything extra after each execution.
Note on scope.
Even though
int i = 0;
int i = 0;
is illegal code because we can't declare i
twice in the same scope,
{
int i = 0;
}
{
int i = 0;
}
is legal because both i
's are in different scopes.
This scoping issue is why we have the while
statement above wrapped in extra {}
's, since the prestatement
belongs in that scope.
Note on continue
.
The keyword continue
can goto
the end of a loop's body.
We can rewrite this behavior more explicitly:
Make the implicit-label explicit by writing it out.
Rewrite continue;
as goto [label's name];
.
For example:
for (long i=0; i < 1000; ++i)
{
if (i % 8 == 0) { continue; }
// rest of body
}
becomes
for (long i=0; i < 1000; ++i)
{
if (i % 8 == 0) { goto end_of_body; }
// rest of body
end_of_body:
}
If we then rewrite this as a while
loop, it'd be
{
long i = 0;
while (i < 1000)
{
if (i % 8 == 0) { goto end_of_body; }
// rest of body
end_of_body:
++i;
}
}
That said, generally goto
and related mechanisms (e.g., continue
) are discouraged. Presumably students ought to understand how they work, though it's generally best to avoid new usage.
for
loops can omit parts.
Might seem weird at first glance, but
for (;;) { }
is actually perfectly legal code! Since it omits a break
condition and doesn't do anything, it's basically an infinite loop that runs forever without doing anything.
In C#, it doesn't consume CPU time, but it also blocks the thread from progressing. For example,
for (;;) { } // Infinite loop
foo(); // Never happens because the above loop never ends
break
, and no post-loop-body expression). $\endgroup$