Two Ways to Change a Loop's Flow
A loop's condition decides when it ends, but sometimes the real answer turns up in the middle of the body. You are searching an array and you find the item on the third element - why check the other 997? Or you are processing a list and one entry is blank - skip it and carry on.
C has one keyword for each case:
break- leave the loop now. Execution resumes at the first statement after it.continue- abandon this pass only. Go on to the next one.
The first loop prints 1 2 3 4 and stops. The second prints 1 2 3 4 6 7 8 9 10 - it skipped one value and kept going.
break in a Loop
The canonical use is a search that stops as soon as it succeeds:
Because found is set before the break, the code after the loop can tell the difference between "found it" and "ran out of elements". That pairing - a result variable plus a break - is the standard C search idiom. The loop counter itself is not usable afterwards when it is declared in the header, since it goes out of scope at the closing brace.
break always exits one loop: the nearest enclosing for, while, do-while, or switch.
continue in a Loop
continue is for entries that should be skipped rather than stop the work:
Where continue jumps to depends on the loop:
for -> the update part of the header (so the counter still advances)
while -> the condition test (nothing else in the body runs)
do-while -> the condition test at the bottom
That difference is not academic. In a for loop, continue can never skip the counter increment, because the increment is in the header. In a while loop it can:
/* BUG: continue skips i++, so this hangs at the first even number */
int i = 0;
while (i < 10) {
if (i % 2 == 0) {
continue;
}
printf("%d ", i);
i++;
}
Either move i++ above the continue, or write it as a for loop, where the header makes it impossible to get wrong.
break in a switch Is Not a break in the Loop
break ends the nearest enclosing loop or switch - whichever is closer. Put a switch inside a loop and every break in it belongs to the switch:
The q command prints its message and the loop keeps running through cc. If quitting was supposed to end the loop, that break did not do it. The fixes are a flag, a goto, or moving the loop into a function and using return - all shown below.
Escaping Nested Loops
A single break leaves one level. Inside two nested loops it only ends the inner one, and the outer loop starts its next pass as if nothing happened.
C has no break 2 and no labelled break. Three honest options:
A flag. Portable, obvious, and slightly noisy:
The flag appears in two places - the outer condition and the assignment - which is the cost. With three levels of nesting it gets genuinely unpleasant.
goto. C's much-maligned jump, and this is the one case where experienced C programmers use it without apology:
A forward goto to a label just after the loops does exactly what a labelled break would do in other languages, in one line and with no flag to keep in sync. The reputation goto has is earned by backward jumps and jumps into the middle of other blocks, which genuinely produce unreadable control flow. A single forward jump out of nested loops is not that. The Linux kernel uses the same pattern for cleanup paths. Use it deliberately and sparingly; do not let the taboo push you into a three-flag alternative that is harder to read.
A function and return. Usually the best answer, because a search deserves a name:
return unwinds every loop in the function, needs no flag and no label, and the searching code now has a name and can be tested on its own. When nesting is deep enough that escaping it is a problem, that is often a hint the block wanted to be a function anyway.
When They Help, and When They Hurt
break and continue earn their place when they let a loop say "this case is finished" once, near the top, instead of wrapping the whole body in an if. Compare:
/* with continue: the real work is not indented */
for (int i = 0; i < n; i++) {
if (!isValid(a[i])) continue;
if (isDuplicate(a[i])) continue;
process(a[i]);
}
/* without: every guard adds a level */
for (int i = 0; i < n; i++) {
if (isValid(a[i])) {
if (!isDuplicate(a[i])) {
process(a[i]);
}
}
}
They hurt when there are many of them. A loop with five scattered breaks and three continues has an exit condition that exists nowhere in writing - a reader has to simulate the whole body to know when it stops. Two guidelines that hold up well: keep the continue guards together at the top of the body, and if a loop has more than one or two breaks, consider whether the condition in the header should have been doing that work.
Two smaller traps. continue in a do-while jumps to the test at the bottom, which is the next thing anyway - harmless, but it surprises people. And break outside any loop or switch is a compile error, which is the one mistake here the compiler catches for you.
Frequently Asked Questions
What is the difference between break and continue in C?
break ends the loop entirely and execution resumes after it. continue abandons only the current pass and goes on to the next one - to the update in a for loop, or straight to the condition test in a while or do-while.
How do I break out of a nested loop in C?
A single break only leaves the innermost loop. To leave both, either set a flag and test it in the outer loop's condition, use goto to jump to a label after the loops, or - usually cleanest - move the loops into a function and return.
Does break exit the loop or just the switch?
Whichever encloses it most tightly. A break inside a switch that is inside a loop ends the switch only; the loop carries on. To leave the loop from inside a switch you need a flag, a goto, or a return.
Why does continue cause an infinite loop in my while loop?
Because continue jumps to the condition and skips the rest of the body - including the counter increment if it sits at the end. In a for loop the update lives in the header so it always runs; in a while loop, move the update before the continue or use a for.