28

I am trying to understand how "continue" works. I understood the concept of the keyword but when I run different programs, it works differently :-/ Let me show you few examples:

If I run this program :

int j = 0;
int i = 0;
LABEL1: for (; i < 3; i++) {
  if (true)
    continue;
}

The value of i is gonna be 3. so far so good. Let's add an outer loop :

int j = 0;
int i = 0;
LABEL2: for (; j < 3; j++) {
  LABEL1: for (; i < 3; i++) {
    if (true)
      continue LABEL2;
  }
}

The value of i is gonna be ... 0 !! I don't understand why i is not incremented if continue is used with a label that goes to the outer loop. Can somebody explain it why ? Do you have some tricky things like that with break ? or with a do {} while ?

I really appreciate any help you can provide.

Xinzz
  • 2,242
  • 1
  • 13
  • 26
user3884432
  • 291
  • 3
  • 6
  • 12
    i is never incremented bc you continue the outter loop – Jay Harris Jul 28 '14 at 13:57
  • 1
    continue with label will go the the position the label indicates. Here continue jumps to LABEL2, so i++ is not executed. – user3761116 Jul 28 '14 at 13:58
  • Thanks guys! I understood. You helped me a lot! I just found something that may help somebody else to understand how continue works with a loop for : continue causes the control flow to jump to the loop condition (for while, do while loops) or to the update (for for loops). This causes control flow to jump to the next iteration. Hey, is it possible to tag it as solved ? – user3884432 Jul 28 '14 at 14:08
  • @user3884432 in order to "mark it as solved" just accept the answer you like most from the below. There are plenty of good ones. If you don't like them, write your own answer and accept that. – Boris the Spider Jul 28 '14 at 14:24
  • Effectively, `continue` branches you to the end of the loop, just before the closing `}`. This results in the loop condition being re-evaluated, just as would occur had your program flow "fallen through" to the bottom of the loop. In the case of `continue label;`, control transfers to the bottom of the loop identified by `label:`. – Hot Licks Jul 29 '14 at 01:00

9 Answers9

28

The basic for statement structure is as follows:

BasicForStatement:
for ( [ForInit] ; [Expression] ; [ForUpdate] ) Statement

Now, from JLS §14.14.1.3. Abrupt Completion of for Statement:

If execution of the Statement completes abruptly because of a continue with no label, then the following two steps are performed in sequence:

  1. First, if the ForUpdate part is present, the expressions are evaluated in sequence from left to right; their values, if any, are discarded. If the ForUpdate part is not present, no action is taken.

  2. Second, another for iteration step is performed.

If execution of the Statement completes abruptly because of a continue with label L, then there is a choice:

  • If the for statement has label L, then the following two steps are performed in sequence:

    1. First, if the ForUpdate part is present, the expressions are evaluated in sequence from left to right; their values, if any, are discarded. If the ForUpdate is not present, no action is taken.

    2. Second, another for iteration step is performed.

  • If the for statement does not have label L, the for statement completes abruptly because of a continue with label L.

(emphasis mine)

ForUpdate, in your case, is i++. Based on what's above:

  • Your first snippet falls under the first case, so i is incremented.

  • Your second snippet falls under the second case, so i is not incremented because the for statement completes abruptly.

Note that if you had continue LABEL1 in your second snippet, i would have been incremented as in your first snippet (in accordance with the JLS).

As a tip for the future, for definitive answers regarding language rules/semantics, you should always consult the language specification. For Java, that's the JLS.

Community
  • 1
  • 1
arshajii
  • 127,459
  • 24
  • 238
  • 287
  • One might also note that 14.14.1.2 specifies that evaluation of [Expression] is part of the iteration step. Otherwise a naive reading of the spec could indicate that neither snippet should terminate. – Taemyr Jul 29 '14 at 12:01
14

This is really normal. The exectuion flow is like this:

  1. j=0
  2. i=0
  3. LABEL 2 loop entered,
  4. LABEL 1 loop entered,
  5. continue to LABEL 2
  6. j++
  7. LABEL 1 loop entered,
  8. continue to LABEL 2
  9. j++
  10. LABEL 1 loop entered,
  11. continue to LABEL 2 ... until j==3
Xinzz
  • 2,242
  • 1
  • 13
  • 26
Frank
  • 157
  • 3
7

i would be increased at the end of the inner loop. But continue LABEL2 jumps out of the inner loop, to the end of the outer loop, so i is not increased; instead only j is increased until the outer loop condition is no longer met.

Maybe it becomes clearer when we rewrite the code with while loops instead:

int j=0;
int i = 0;
while (j<3) {
    while(i<3) {
       if (true)
           goto END_OF_LOOP2;

       END_OF_LOOP1: i++;
    }
    END_OF_LOOP2: j++;
}
Erich Kitzmueller
  • 36,381
  • 5
  • 80
  • 102
6

Continue simply does what its name suggests, it immediately continues to the next execution of the loop without executing the rest of the code in the loop.

So if you have a loop like this:

int j=0;
int i = 0;
    LABEL1 : for(;i < 3; i++){
        if (true) {
            continue;
        }
        someOtherMethod();
    }

The someOtherMethod part is never executed because you will always hit the continue.

The reason your counter is never incremented has to do with labels, you can mark a loop with a label (in your case LABEL1 and LABEL2 and use that label to continue one of the outer loops of your inner loop.

So with your code the loop of LABEL1 never gets a chance to increment its counter and thus i remains 0 because your continue statement immediately continues to the next iteration of the outer loop.

Remcoder
  • 215
  • 2
  • 12
4
continue LABEL2; 

causes that only the outter loop increasing. if you have

LABEL2 : for(;j <3;j++){
    LABEL1 : for(;i < 3; i++){
             if (true)
                 continue LABEL1;
             }
     }

i will increase.

betteroutthanin
  • 7,148
  • 8
  • 29
  • 48
3

If this is the code, for example:

    int main (){
      // Local variable declaration:

    int a = 10;

   // do loop execution
  do
  {
     if( a == 15)
     {
        // skip the iteration.
        a = a + 1;
        continue;
      }
      cout << "value of a: " << a << endl;
           a = a + 1;
         }while( a < 20 );
         return 0;
     }

Then the result will be

value of a: 10
value of a: 11
value of a: 12
value of a: 13
value of a: 14
value of a: 16
value of a: 17
value of a: 18
value of a: 19

POINT TO BE NOTED: "value of a: 15" is not in the output. continue in programming language skips that certain line in a loop, if "break" used, then break just gets off that line after "14" (in this case).
For your understanding, please see the following flowchart:

enter image description here

Shayan Ahmad
  • 952
  • 8
  • 17
3

i is incremented when next time condition is checked.

If you continue or break the loop then condition will not be checked again and will never increment the value of i.

for

LABEL1 : for(;i < 3; i++){
               if (true)
                   continue;
             }

when you continue you're again checking if value of i is less then 3 at that moment before checking that condition compiler internally increments the value of i.

Here

LABEL2 : for(;j <3;j++){
        LABEL1 : for(;i < 3; i++){
                 if (true)
                     continue LABEL2;
                 }
         }

When you're executing continue condition for Label1 is never checked again, and will directly go to the statement with Label2 so it will never get incremented.

Same is with the break

LABEL1 : for(;i < 3; i++){
               if (true)
                   break;
             }

if you execute the above code value of i will be 0 and not 1.

Parth Soni
  • 11,158
  • 4
  • 32
  • 54
2

If you run this in debug mode, you will see what happens. In short, whenever you enter the inner loop to increment the i, you will instead continue to LABEL2 instead of incrementing i and going to the next iteration of the inner loop.

Thus, you will be in the outer loop 3 times and you will never hit the i++ in the inner loop.

If it's easier, think of the inner for loop like a while loop:

int i = 0, j = 0;
LABEL2: for (; j < 3; j++) {
  LABEL1: while (i < 3) {
    if (true) {
      continue LABEL2;
    }

    i++;
  }
}
Xinzz
  • 2,242
  • 1
  • 13
  • 26
0

A continue statement without a label will re-execute from the condition the innermost while or do, or loop, and from the update expression the innermost for loop. It is often used to early-terminate a loop's processing and thereby avoid deeply-nested if statements. In the following example continue will get the next line, without processing the following statement in the loop.

while (getNext(line)) {
  if (line.isEmpty() || line.isComment())
    continue;
  // More code here
}

With a label continue will execute in the same way the correspondingly labeled loop. This can be used to escape deeply-nested loops, or simply for clarity. If you're truly perverse you can also use it to simulate a limited form of goto. In the following example the continue will re-execute the for (;;) loop.

aLoopName: for (;;) {
  // ...
  while (someCondition)
  // ...
    if (otherCondition)
      continue aLoopName;

Sometimes continue is also used as a placeholder in order to make an empty loop body clearer.

for (count = 0; foo.moreData(); count++)   continue;

The same statement without a label also exists in C and C++. In Perl it's named next.

source

Community
  • 1
  • 1
Dhrumil Shah
  • 736
  • 6
  • 15