11

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
    ...
}
timss
  • 9,982
  • 4
  • 34
  • 56
Thokchom
  • 1,602
  • 3
  • 17
  • 32
  • Look at the output assembly and you'll see that for loops are not expanded how you think. – Jesus Ramos May 16 '13 at 22:04
  • 3
    Q: What happens if you put `continue` *AFTER* `i++` in your "while" loop? Q: You understand that the initialization, increment, and condition are all part of the same construct in your "for" loop? That they're always executed, independent of what happens inside the loop? – paulsm4 May 16 '13 at 22:05
  • @JesusRamos I haven't progressed yet to that level where assembly would make sense to me!! – Thokchom May 16 '13 at 22:05
  • @paulsm4 But doesn't the third statement of `for` loop come after the loop body each time and `continue` is expected to ignore everything that comes after it?Why is it ignoring the `i++` of while then? – Thokchom May 16 '13 at 22:06
  • Another contradictory claim--**A continue statement in a for statement causes the first expression of the for statement to be evaluated**---http://msdn.microsoft.com/en-IN/library/0ceyyskb(v=vs.80).aspx – Thokchom May 16 '13 at 22:09
  • Q: But doesn't the third statement of for loop come after the loop body each time. A: Yes. Q: ...continue is expected to ignore everything that comes after it? A: No :) – paulsm4 May 16 '13 at 22:11
  • @paulsm4 Please look into the link I gave and the statement I quoted.That is very much confusing.How can the control pass to the first statement of the for loop?That way the counter will be set to original value each time!!That contradicts what I know,and what you are telling me.That **Microsoft** site I mean. – Thokchom May 16 '13 at 22:17
  • 1
    Thokchom, I suggest you find some better doco than what MS has provided :-) – paxdiablo May 16 '13 at 22:18
  • @paxdiablo Please confirm it.What is said there about `continue`, that it passes control to first statement of `for`loop, is **wrong** ?I am not sure because Microsoft is supposed to be synonymous with trust.Even my OS is Microsoft product. – Thokchom May 16 '13 at 22:21
  • 1
    MS synonymous with trust? I decline to comment :-) Whether it's wrong or misunderstood, I'll leave for you to decide. It _does_ pass control back to the first statement of the `for` body but _only_ after executing the post-op stuff first. – paxdiablo May 16 '13 at 22:25
  • @paxdiablo There it seems to say the condition is checked after the first statement...`A continue statement in a for statement causes the first expression of the for statement to be evaluated. Then the compiler reevaluates the conditional expression and, depending on the result` – Thokchom May 16 '13 at 22:30
  • 2
    Thokchom, I think that's a typo, the conditional expression is the middle one, so I suspect what they meant was "... causes the _third_ expression of the for statement to be evaluated". – paxdiablo May 16 '13 at 22:45
  • Why is anybody even looking at vendor documentation for C compilers rather than reading a proper C book or the standard? This is the second time in the past two days that a vendor's bogus documentation had somebody confused (the last time, it was IBM's fault). – R.. GitHub STOP HELPING ICE May 16 '13 at 23:50
  • For what it's worth, the MSDN pages for VS2008+ are accurate. – Anthony May 16 '13 at 23:55

8 Answers8

29

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.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • I'll be dead!!The Microsoft site has another contradictory description.It says `A continue statement in a for statement causes the first expression of the for statement to be evaluated`--http://msdn.microsoft.com/en-IN/library/0ceyyskb(v=vs.80).aspx Can you explain how come control goes to first statement of `for` loop? – Thokchom May 16 '13 at 22:08
  • @Thokchom, given that the link on that page leading to the `for` statement doesn't even describe the third section (the post-op), I'd be relying on something else to learn. – paxdiablo May 16 '13 at 22:16
  • @Thokchom the description on that page is horribly broken. The link they provide tot he page describing the `for` statement explicitly is accurate. You may want to consider submitting a correction request. – Nik Bougalis May 16 '13 at 22:36
  • @NikBougalis Can't believe a Microsoft site can be so unprofessional. – Thokchom May 16 '13 at 22:38
  • @Thokchom Relax, mistakes happen. Especially when you have to maintain a website with as much content as MSDN. – Nik Bougalis May 16 '13 at 22:40
  • @Thokchom: Yesterday we had a question where it was IBM's documentation for the C compiler on AIX that was similarly bogus. **Don't** rely on vendor documentation. Read the C standard or a reputable book on C. – R.. GitHub STOP HELPING ICE May 16 '13 at 23:51
11

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).

jxh
  • 69,070
  • 8
  • 110
  • 193
  • @Thokchom: The difference is that the last formulation would allow your `continue` in the `while` loop to continue to increment. – jxh May 16 '13 at 22:29
  • Oh..that will be handy when one wants the `continue` **not to** ignore the increment.Nice trick! +1 – Thokchom May 16 '13 at 22:32
  • @Thokchom: Thanks, I updated the answer to make my intention more clear. – jxh May 16 '13 at 22:36
3

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

while(i<10)   //causes infinite loop
{
.........
continue
i++
......
}
karthikr
  • 97,368
  • 26
  • 197
  • 188
2

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.

CmdrMoozy
  • 3,870
  • 3
  • 19
  • 31
0

Because the third part of the for is always executed.

Thomas Ruiz
  • 3,611
  • 2
  • 20
  • 33
0

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).

sarbjit
  • 3,786
  • 9
  • 38
  • 60
0

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.

Sahas
  • 1
0

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)