Why is 'continue' statement ignoring the loop counter increment in 'while' loop, but not in 'for' loop?

StackOverflow https://stackoverflow.com/questions/16598222

Question

Why does it tend to get into an infinite loop if I use continue in a while loop, but works fine in a for loop?
The loop-counter increment i++ gets ignored in while loop if I use it after continue, but it works if it is in for loop.

If continue ignores subsequent statements, then why doesn't it ignore the third statement of the for loop then, which contains the counter increment i++? Isn't the third statement of for loop subsequent to continue as well and should be ignored, given the third statement of for loop is executed after the loop body?

while(i<10)   //causes infinite loop
{
    ...
    continue
    i++
    ...
}

for(i=0;i<10;i++)  //works fine and exits after 10 iterations
{
    ...
    continue
    ...
}
Was it helpful?

Solution

Because continue goes back to the start of the loop. With for, the post-operation i++ is an integral part of the loop control and is executed before the loop body restarts.

With the while, the i++ is just another statement in the body of the loop (no different to something like a = b), skipped if you continue before you reach it.

OTHER TIPS

The reason is because the continue statement will short-circuit the statements that follow it in the loop body. Since the way you wrote the while loop has the increment statement following the continue statement, it gets short-circuited. You can solve this by changing your while loop.

A lot of text books claim that:

for (i = 0; i < N; ++i) {
    /*...*/
}

is equivalent to:

i = 0;
while (i < N) {
    /*...*/
    ++i;
}

But, in reality, it is really like:

j = 0;
while ((i = j++) < N) {
    /*...*/
}

Or, to be a little more pedantic:

i = 0;
if (i < 10) do {
    /*...*/
} while (++i, (i < 10));

These are more equivalent, since now if the body of the while has a continue, the increment still occurs, just like in a for. The latter alternative only executes the increment after the iteration has completed, just like for (the former executes the increment before the iteration, deferring to save it in i until after the iteration).

Your increment of i is after continue, so it never gets executed

while(i<10)   //causes infinite loop
{
.........
continue
i++
......
}

In any loop, continue moves execution back to the top of the loop, not executing any other instructions after the continue statement.

In this case, the for loop's definition is always executed (per standard C), whereas the i++; statement is NOT executed, because it comes AFTER the continue statement.

Because the third part of the for is always executed.

continue statement jumps the control to the end of the statements in current iteration of loop i.e. it skips the execution of the statements in the current iteration and moves to the next iteration of the loop.

With while loop, continue statement causes control to reach the end of statements (including increment statement), thus causing loop to continue forever.

With for loop, continue statement jumps the control to end of statement and excutes the increment statement (In for loop, increment statement is considered seperate from the statments written within the body of the loop).

for loop holds condition statements and increment, so when the condition is satisfied it goes to execute the statement inside for loop,but if write continue statement than it will again reached to first line of for loop i.e. increment and checking of condition statement, if satisfied than again comes in for execution. For while loop it just checks the condition statement and if condition satisfied it goes for the execution of statements in the while loop. so continue will not execute any line after it.and hence your condition satisfied every time and goes for the infinite loop.

continue bypasses the rest of the block and begins again at the top of the block if the conditional of the loop is met.

The next question is: "What do I do, then?" There are two answers I can think of.

Example:

void foo ()
{
    size_t i = 0;
    do
    {
        /*...*/
        if ( /*...*/ )
        {
            /*...*/
            continue;
        }
        /*...*/
        i++;
    } while ( /* loop conditional */ );
}

Solution #1: Manually Increment

void foo ()
{
    size_t i = 0;
    do
    {
        /*...*/
        if ( /*...*/ )
        {
            /*...*/
            i++;
            continue;
        }
        /*...*/
        i++;
    } while ( /* loop conditional */ );
}

Solution #2: A uniquely valid application of goto*

void foo ()
{
    size_t i = 0;
    do
    {
        /*...*/
        if ( /*...*/ )
        {
            /*...*/
            goto foo_next;
        }
        /*...*/
foo_next:
        i++;
    } while ( /* loop conditional */ );
}

goto is valid in this case because incrementation in two places is technically the same instruction. This solution is especially relevant when the per-iteration-volatile variables are more complex; such as, setting multiple variables or modifying a value with an equation or function.

In the event of a single increment or decrement statement, Solution #1 may prove favorable; however, it should be noted that: if the code is modified after such an implementation, one must remember to update both instances of the statement (which may be prone to bugs, especially if the modifications take place after an extended period of time**). Therefore, I highly reccomend Solution #2.

*Some consider any and all use of goto bad practice. I recommend you decide for yourself, and leave you this: google for "c goto bad"

**A comment reminding of this necessity may suffice, but — if my advice has been followed — the per-iteration-volatile variables in are restricted to a single statement. And I quote:

There is never a reason to comment a single line

-Linus Torvalds (source: http://yarchive.net/comp/linux/coding_style.html)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top