C goto Statement

Beginner
⏱️ 11 min read
📚 Updated: Jul 2026
🎯 5 Examples
Unconditional jump

What You’ll Learn

The goto statement jumps to a label in the same function—no condition attached. Most beginner code should use if, loops, and break instead, but goto still appears in cleanup patterns and for escaping deeply nested loops. This tutorial explains syntax, legitimate uses, pitfalls, five examples, and when not to use it.

01

Label

name:

02

goto

Jump there.

03

Same fn

Only local.

04

Nested

Exit loops.

05

Cleanup

Error path.

06

Sparingly

Rare use.

Definition and Usage

The goto statement transfers control to a labeled statement in the same function. A label is an identifier followed by a colon (done:). The jump is unconditional—unlike if, nothing is tested at the goto itself.

Structured programming favors if, for, while, and functions. Still, you may see goto in Linux kernel code and in centralized cleanup blocks that free memory or close files after failures. Know what it does; use it only when the benefit is clear.

💡
Beginner Tip

If you reach for goto to fix messy logic, try extracting a function or using a break with a flag first. Reserve goto for patterns like “jump to cleanup at the bottom of one function.”

📝 Syntax

General form of goto and a label:

C
goto label_name;
/* ... other statements ... */
label_name:
    statement;

Rules

  • Same function — label and goto must live in one function.
  • Forward or backward — both directions are legal in C.
  • Label scope — visible throughout the enclosing function.
  • Not into a block — cannot jump into the middle of a scope that skipped initialization (compiler may reject).

Compile

C
gcc program.c -std=c11 -o program

⚡ Quick Reference

PatternExample
Forward jumpgoto done; ... done: return 0;
Exit nested loopsgoto exit_loops; after match
Error cleanupif (fail) goto cleanup; ... cleanup: free(p);
vs breakbreak exits one loop; goto can leave several
InvalidJump to label in another function
Syntax
goto L;

Unconditional

Label
L:

Target

Scope
one function

Same fn only

Prefer
if / break

Usually

Examples Gallery

Compile with gcc example.c -std=c11 -o example. Each program shows a different goto pattern—study them, but prefer structured code in your own projects.

📚 Getting Started

Classic nested-loop exit and error handling from the reference material.

Example 1 — Exit Nested Loops

break only leaves the inner loop; goto can leave both at once.

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

At i == 1 and j == 1, execution jumps to exit_loops: and skips the rest of both loops. A done flag checked in both loop headers achieves the same without goto.

Example 2 — File Open Error Handling

Jump to a shared error block when fopen fails.

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

int main(void) {
    FILE *file = fopen("missing.txt", "r");

    if (file == NULL) {
        goto error;
    }

  /* would read/process file here */
    fclose(file);
    return 0;

error:
    fprintf(stderr, "Failed to open the file\n");
    return 1;
}

How It Works

When the file is missing, fopen returns NULL and goto error runs the cleanup message. In small programs, a simple if (file == NULL) { ... return 1; } is often enough without goto.

📈 Practical Patterns

Forward jumps, search, and multi-step cleanup.

Example 3 — Forward Jump to End

Skip remaining steps when a value is invalid.

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

goto end skips “Processing” lines. An else branch or early return would be clearer here—this shows forward jumps only.

Example 4 — Find Value in a Matrix

Search a 2D array and leave both loops when the target is found.

C
#include <stdio.h>

int main(void) {
    int grid[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };
    int target = 5;
    int found_row = -1, found_col = -1;

    for (int r = 0; r < 3; r++) {
        for (int c = 0; c < 3; c++) {
            if (grid[r][c] == target) {
                found_row = r;
                found_col = c;
                goto found;
            }
        }
    }

found:
    if (found_row >= 0) {
        printf("Found %d at row %d, col %d\n", target, found_row, found_col);
    } else {
        printf("%d not found\n", target);
    }

    return 0;
}

How It Works

Without goto, you would set a found flag and break from the inner loop, then break the outer loop if the flag is set. goto found is compact for a one-off search.

Example 5 — Centralized malloc Cleanup

One label frees everything when any allocation step fails.

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;
    }

    a[0] = 42;
  printf("Allocated and used both buffers.\n");

cleanup:
    free(b);
    free(a);
    if (status != 0) {
        printf("Cleanup after error code %d\n", status);
    }

    return status;
}

How It Works

cleanup: always runs free on pointers (safe on NULL). This pattern appears in kernel and library C code. In application code, smaller functions or a do { ... } while(0) macro sometimes replace it.

🚀 Common Use Cases

  • Nested loop exit — leave two or more loops at once.
  • Resource cleanup — one block frees memory, closes files.
  • Error paths — jump to shared failure handling in long functions.
  • Kernel/driver code — low-level C where structured escape is awkward.
  • Generated parsers — some tools emit goto for state machines.
  • Avoid in app logic — menus and business rules belong in if/switch.

🧠 How goto Works

1

Define a label

label_name: marks a jump target in the function.

Label
2

Execute goto

goto label_name; runs when reached (often after an if).

Jump
3

Skip intermediate code

Statements between goto and the label do not run.

Bypass
=

Continue at label

Execution resumes at the labeled statement and proceeds normally afterward.

📝 Notes

  • goto cannot cross function boundaries.
  • Labels do not change scope—variables declared after a label were not initialized if you jumped over their declaration.
  • Dijkstra’s famous note argued against unrestricted goto; modern style favors structure.
  • break and continue are not substitutes for cross-function exit—use return.
  • Name labels clearly: cleanup:, error:, not single letters in large files.
  • This is the last tutorial in the control statements series.

⚡ Optimization

goto is a direct jump at machine level—no meaningful speed advantage over well-written if and loops on modern compilers. Readability and maintainability matter far more. Choose structure over micro-optimization.

Conclusion

goto jumps to a label in the same function. It can simplify nested-loop exit and centralized cleanup, but overuse creates spaghetti code. Default to if, loops, break, and return—know goto so you can read real-world C, not so you can sprinkle it everywhere.

You have finished the control statements track. Continue with C Loops to master repetition next.

💡 Best Practices

✅ Do

  • Use descriptive label names (cleanup, error)
  • Keep goto jumps short and local in one function
  • Consider goto for multi-resource cleanup blocks
  • Prefer return to leave functions
  • Read kernel/library code that uses goto—do not copy blindly

❌ Don’t

  • Replace every if-else with goto
  • Jump into blocks that skip variable initialization
  • Use goto between functions (illegal)
  • Create loops only with backward goto
  • Ignore clearer alternatives (break, flags, helpers)

Key Takeaways

Knowledge Unlocked

Five things to remember about goto

Unconditional jumps in C.

5
Core concepts
🔢 02

Label

name:

Target
🕸 03

Same fn

Only local.

Scope
📝 04

Cleanup

Real use.

Pattern
⚠️ 05

Sparingly

Rarely.

Style

❓ 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.
Did you know?

C++ added restrictions so you cannot goto over declarations that need constructors—plain C has fewer rules, but jumping past int x = 5; without running the initializer is still undefined behavior territory. Keep labels below your declarations or use blocks carefully.

Continue to C Loops

Control statements are complete—learn for, while, and do-while next.

C Loops hub →

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.

6 people found this page helpful