C goto Statement

Beginner
6 min read
Updated: Oct 2026
3 examples
Live preview

What Is goto?

goto jumps to a label in the same function. Use it sparingly—prefer if, loops, break, and return. Acceptable rare uses: leave nested loops, or one shared cleanup block.

Remember
goto label_name;     // jump now

label_name:
    /* execution continues here */

same function only   → cannot jump across functions
forward or backward  → both allowed
prefer structured    → if / for / while / break / return
UsePrefer
Exit one loopbreak
Exit nested loops / shared cleanupgoto (or a flag / helper)
Leave a functionreturn

How to Use goto in C

Define a label, then jump to it with goto—only inside one function.

  1. Pick a clear label name (e.g. cleanup, found).
  2. Write the label as name: before the target statement.
  3. Call goto name; when you need that jump.
  4. Ask first: can break, a flag, or return do the same more clearly?
PieceRequired?Role
goto label;YesUnconditional jump
label:YesLanding point in the same function
Same functionYesCannot cross function boundaries

Pseudocode

Pseudocode
for each row:
    for each col:
        if cell == target:
            save position
            goto found      // leave both loops

found:
    if saved:
        print position
    else:
        print "not found"

// cleanup style:
allocate A
if fail → goto cleanup
allocate B
if fail → goto cleanup
use A and B

cleanup:
    free what was allocated
    return status

Cheat Sheet

Keep these facts handy—and default to structured control.

TopicDetail
Syntaxgoto label;  /  label:
ScopeSame function only
DirectionForward or backward
vs breakbreak = one loop; goto can leave many
Good usesNested-loop exit, shared cleanup
AvoidEveryday branching, “goto loops,” spaghetti jumps
Compilegcc file.c -std=c11 -o out

Live Preview

Simulate common goto patterns. Same idea as the C examples below.

Browser simulation of goto control flow (same idea as the C examples below).

Result
i=0 j=0,1,2 printed
i=1 j=0 printed
i=1 j=1 → goto exit_loops
both loops left

Worked Walkthrough — Leave Nested Loops

At i == 1 and j == 1, jump past both loops. break alone cannot do that.

Trace
outer i = 0..2
  inner j = 0..2
    if i==1 and j==1 → goto exit_loops

Trace:
  (0,0) (0,1) (0,2) print
  (1,0) print
  (1,1) → goto exit_loops
  (1,2) and i=2 never run

exit_loops:
  print "Exited the loops"

Alternative without goto:
  set done = true; break; then break outer if done

C Examples

Compile every example with gcc file.c -std=c11 -o out. Learn the syntax—then prefer structured alternatives when they are clearer.

Example 1 — Exit Nested Loops

Leave both loops at once. A single break would only exit the inner loop.

C
#include <stdio.h>

int main(void) {
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (i == 1 && j == 1) {
                goto exit_loops;
            }
            printf("i = %d, j = %d\n", i, j);
        }
    }

exit_loops:
    printf("Exited the loops\n");

    return 0;
}

How It Works

  1. Nested loops. Outer i and inner j each run 0–2.
  2. Match. When i == 1 and j == 1, goto exit_loops runs.
  3. Jump out. Remaining pairs are skipped; both loops end.
  4. Land at the label. Exited the loops prints, then return 0.

Example 2 — Forward Jump to End

Skip remaining work on invalid input. In new code, an early return or else is often clearer—this shows the jump.

C
#include <stdio.h>

int main(void) {
    int n = -5;

    if (n < 0) {
        printf("Invalid input: %d\n", n);
        goto end;
    }

    printf("Processing %d...\n", n);
    printf("Done processing.\n");

end:
    printf("Program finished.\n");

    return 0;
}

How It Works

  1. Check input. n is -5, so n < 0 is true.
  2. Report error. Print the invalid-input message.
  3. Jump forward. goto end skips the “Processing” lines.
  4. Shared finish. The end: label always prints the final line.

Example 3 — Centralized Cleanup

One label frees resources if any allocation fails—a classic rare-but-valid use.

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

int main(void) {
    int *a = NULL;
    int *b = NULL;
    int status = 0;

    a = malloc(10 * sizeof *a);
    if (a == NULL) {
        status = 1;
        goto cleanup;
    }

    b = malloc(10 * sizeof *b);
    if (b == NULL) {
        status = 2;
        goto cleanup;
    }

    printf("Both allocations OK\n");

cleanup:
    free(a);
    free(b);
    if (status != 0) {
        fprintf(stderr, "Allocation failed (step %d)\n", status);
    }
    return status;
}

How It Works

  1. Allocate A. On failure, set status and jump to cleanup.
  2. Allocate B. Same pattern if the second malloc fails.
  3. Success path. If both work, print OK, then fall into cleanup.
  4. Always free. free(NULL) is safe, so one block frees whatever was allocated.

Edge Cases & Pitfalls

Treat goto as a last resort—not a default tool.

scope

Same function only

You cannot goto into another function. Use return (or a call) to leave or enter functions.

style

Spaghetti code

Many scattered jumps make flow hard to follow. Prefer if, loops, and small functions.

vars

Jumping over declarations

Skipping past a variable’s declaration into a block that uses it can be undefined or a compile error. Keep labels and jumps simple.

alt

Often replaceable

Flags + break, early return, or a helper function usually replace everyday goto use.

Performance Notes

ApproachCostBest for
goto out of nestsNegligible (one jump)Deep nested search / multi-level exit
Flag + dual breakTiny checks; clearer to many readersBeginner / team code style
Helper + returnCall overhead (usually irrelevant)Reusable search or cleanup logic

Performance is not why people avoid goto—readability is. Use it when it clearly simplifies cleanup or multi-level exit.

Key Takeaways

  • Role: jump to a label in the same function.
  • Rare use: nested-loop exit and shared cleanup.
  • Default: prefer if, loops, break, return.
  • Risk: too many jumps → hard-to-follow “spaghetti” code.

One line: know goto, use it rarely, and keep labels purposeful.

Frequently Asked Questions

goto transfers control unconditionally to a label in the same function. Syntax: goto label_name; and label_name: before a statement. Execution continues at the label.
No. goto and its label must be in the same function. You cannot jump into or out of a function with goto. Use return for leaving functions.
Yes. goto can jump forward or backward within a function, as long as the label is in scope. Backward jumps can create loops but are usually clearer written as for or while.
Rarely. Common acceptable uses: centralized cleanup after failed steps (free resources), breaking out of deeply nested loops, and some kernel/driver code. Prefer if, loops, break, and return in beginner programs.
Spaghetti code jumps unpredictably with many gotos, making flow hard to follow. Excessive goto creates this style. Structured control (if, for, while, functions) keeps programs readable.
Use break or a flag for nested loops, return for leaving functions, else-if or switch for branching, and small helper functions to simplify complex flow. break exits one loop; goto can exit several in one jump.

Next: C Loops

Practice for, while, and do-while—the structured way to repeat work.

loops tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

9 people found this page helpful