Skip to content
Laviyx Learn

Try

C course menu

break, continue and goto in C

Learn how to control loops in C with break and continue, break inside switch, leaving nested loops with a flag or a function, and the limited, legitimate use of goto for cleanup in error handling.

Beginner7 min readUpdated
On this page

break and continue change how a loop runs. C also has goto, which jumps to a label; it is rarely needed, but one pattern for it is common in real C code.

break#

break leaves the innermost loop (or switch) immediately:

C
int orders[] = {120, 450, 80, 990, 300};
int first_big = -1;
for (int i = 0; i < 5; i++) {
    printf("checking %d\n", orders[i]);
    if (orders[i] > 400) {
        first_big = orders[i];
        break;
    }
}
printf("First order over 400: %d\n", first_big);
Output
checking 120
checking 450
First order over 400: 450

continue#

continue skips the rest of the current repetition and goes to the next one. In a for loop, the update (i++) still runs:

C
for (int i = 1; i <= 10; i++) {
    if (i % 3 == 0) continue;
    printf("%d ", i);
}
printf("\n");
Output
1 2 4 5 7 8 10 

Leaving nested loops#

break only leaves the innermost loop. Two clean ways to stop an outer loop:

C
#include <stdio.h>

/* 1. Put the loops in a function and return */
int find(int grid[3][3], int target, int *row, int *col) {
    for (int r = 0; r < 3; r++) {
        for (int c = 0; c < 3; c++) {
            if (grid[r][c] == target) {
                *row = r;
                *col = c;
                return 1;
            }
        }
    }
    return 0;
}

int main(void) {
    int grid[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    int r, c;
    if (find(grid, 6, &r, &c)) printf("Found at row %d, column %d\n", r, c);

    /* 2. Use a flag */
    int found = 0;
    for (int i = 0; i < 3 && !found; i++) {
        for (int j = 0; j < 3; j++) {
            if (grid[i][j] == 8) {
                found = 1;
                printf("8 is at %d,%d\n", i, j);
                break;
            }
        }
    }
    return 0;
}
Output
Found at row 1, column 2
8 is at 2,1

The function version uses pointers (int *row) to return the position; pointers are explained in Pointers.

goto#

goto label; jumps to label: in the same function. Jumping around freely makes code very hard to follow, so most code never uses it. One accepted use is cleanup on error: when a function acquires several resources and any step can fail, jumping to a shared cleanup section avoids repeating the cleanup code:

C
#include <stdio.h>
#include <stdlib.h>

int process(void) {
    int result = -1;
    int *data = malloc(100 * sizeof *data);
    if (data == NULL) goto done;

    FILE *f = fopen("missing-file.txt", "r");
    if (f == NULL) goto free_data;

    /* ... use f and data ... */
    result = 0;
    fclose(f);

free_data:
    free(data);
done:
    return result;
}

int main(void) {
    printf("process returned %d\n", process());
    return 0;
}
Output
process returned -1

The file does not exist, so the function jumps to free_data, frees the memory and returns an error. This pattern is common in operating system and library code; Error Handling shows it in context.

Practice#

Practice exercise

Loop through the numbers 1 to 50. Skip numbers that are not divisible by 7, print the ones that are, and stop completely after printing the first one greater than 30.

Show solution
C
#include <stdio.h>

int main(void) {
    for (int n = 1; n <= 50; n++) {
        if (n % 7 != 0) continue;
        printf("%d ", n);
        if (n > 30) break;
    }
    printf("\n");
    return 0;
}
Output
7 14 21 28 35 

Key takeaway#

Finished this lesson?