The goto statement is one of the most discussed topics in C programming.
Background
The goto statement appeared in early programming languages to simplify writing branches and loops, when other mechanisms were not yet available. In C, it was retained for compatibility and relatively rare cases when conventional constructs are not suitable.
Problem
goto simplifies the implementation of some low-level algorithms (e.g., complex error handling), but it easily turns code into "spaghetti" with tangled control flow. Incorrect use complicates testing, understanding, and maintaining code.
Solution
Using goto is permissible for controlling exits from deeply nested loops or centralized resource cleanup — for instance, when errors occur in a function where multiple resources allocated at different stages need to be sequentially freed.
Example code:
#include <stdio.h> #include <stdlib.h> int process() { int *a = malloc(10 * sizeof(int)); if (!a) return -1; int *b = malloc(20 * sizeof(int)); if (!b) goto cleanup_a; // ... free(b); cleanup_a: free(a); return 0; }
Key features:
Can goto jump to another function or exit a function?
No, the goto operator can only jump within the same function — to a label in the same function. Attempting to jump between functions will result in a compilation error.
Can you use goto to enter a block of variable declarations?
Strictly prohibited! Entering via goto into a block where variables are declared with automatic initialization leads to undefined behavior.
Example code:
void bad() { goto label; int x = 5; label: printf("%d ", x); // undefined behavior }
Are the continue and break operators goto?
No. The break and continue statements are specialized for controlling loops and while they superficially resemble goto in the idea of jumping, they only operate at the level of the nearest outer loops, while goto operates on a label declared within a function.
Pros: Allows compact error handling and resource deallocation; can sometimes simplify exits from deeply nested structures.
Cons: Easily creates "spaghetti code"; complicates maintenance; violates structured programming principles.
Negative case:
In a project, there are nearly 50 goto jumps, some going backward in the text. As a result, understanding the logic is extremely difficult, leading to an increase in errors, confusion, and high maintenance costs. Pros: quickly written, cons: almost impossible to understand and modify.
Positive case:
In a function initializing a large object, goto is only used for centralized resource deallocation upon error. The code is concise, easily maintainable, and allows for adding new resources. Pros: readability, prevention of memory leaks; cons: some consider goto an anti-pattern — it requires careful application.