C Goto Statement

Jump to specific labels in your code (use with caution)

🎯 What is Goto Statement?

The goto statement in C allows unconditional jumps to labeled statements within the same function. While powerful for specific cases like error handling, it should be used sparingly to maintain code readability and structure.


// Simple goto example
#include <stdio.h>

int main() {
    int num = 5;
    
    if(num > 0) {
        goto positive;
    }
    
    printf("Number is not positive\n");
    goto end;
    
positive:
    printf("Number is positive: %d\n", num);
    
end:
    printf("Program finished\n");
    return 0;
}
                                    

Output:

Number is positive: 5
Program finished

Goto Components

🏷️

Label

Target destination for jump

label_name:
➡️

Goto Statement

Jump command to label

goto label_name;
🎯

Forward Jump

Jump to label below

goto skip;
// code
skip:
🔄

Backward Jump

Jump to label above

loop:
// code
goto loop;

🔹 Basic Goto Syntax

The goto statement provides unconditional transfer of control to a labeled statement within the same function, though its use is generally discouraged in modern programming. Labels are identifiers followed by a colon, and goto label_name; jumps directly to that label's location. For example, goto error_handler; jumps to error_handler: label elsewhere in the function. While considered harmful for creating spaghetti code, goto has legitimate uses: breaking out of deeply nested loops, implementing cleanup code in error handling before structured exception handling existed, and in state machines. However, modern programming favors structured alternatives like break, continue, return, and proper function decomposition that improve code maintainability and readability.

// Basic syntax
label_name:
    // code here

goto label_name;

// Example: Simple jump
#include <stdio.h>

int main() {
    printf("Start\n");
    goto middle;
    
    printf("This won't print\n");
    
middle:
    printf("Middle section\n");
    goto end;
    
    printf("This also won't print\n");
    
end:
    printf("End\n");
    return 0;
}

Output:

Start
Middle section
End

🔹 Legitimate Use Cases

🔸 Error Handling and Cleanup

The goto statement is most legitimately used for error handling and resource cleanup in C programming. When multiple operations require proper cleanup if any step fails, goto provides an efficient way to jump to a cleanup label that properly releases allocated resources. This approach prevents resource leaks by ensuring files are closed, memory is freed, and buffers are released regardless of where an error occurs. For example, if file opening, memory allocation, or file creation fails, goto cleanup; jumps directly to the cleanup section where all resources are properly deallocated, making the code safer and more maintainable than multiple nested error checks.

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

int main() {
    FILE *file1 = NULL, *file2 = NULL;
    int *buffer = NULL;
    
    // Open first file
    file1 = fopen("input.txt", "r");
    if(!file1) {
        printf("Error: Cannot open input file\n");
        goto cleanup;
    }
    
    // Allocate memory
    buffer = malloc(1000 * sizeof(int));
    if(!buffer) {
        printf("Error: Memory allocation failed\n");
        goto cleanup;
    }
    
    // Open second file
    file2 = fopen("output.txt", "w");
    if(!file2) {
        printf("Error: Cannot create output file\n");
        goto cleanup;
    }
    
    printf("All resources allocated successfully\n");
    // Process files here...
    
cleanup:
    if(file1) fclose(file1);
    if(file2) fclose(file2);
    if(buffer) free(buffer);
    printf("Cleanup completed\n");
    
    return 0;
}

Output (if files don't exist):

Error: Cannot open input file
Cleanup completed

🔸 Breaking Out of Nested Loops

#include <stdio.h>

int main() {
    int found = 0;
    int matrix[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    int target = 5;
    
    printf("Searching for %d in matrix:\n", target);
    
    for(int i = 0; i < 3; i++) {
        for(int j = 0; j < 3; j++) {
            printf("Checking [%d][%d] = %d\n", i, j, matrix[i][j]);
            
            if(matrix[i][j] == target) {
                printf("Found %d at position [%d][%d]\n", target, i, j);
                goto found_target;
            }
        }
    }
    
    printf("Target not found\n");
    goto end;
    
found_target:
    printf("Search completed successfully\n");
    
end:
    return 0;
}

Output:

Searching for 5 in matrix:
Checking [0][0] = 1
Checking [0][1] = 2
Checking [0][2] = 3
Checking [1][0] = 4
Checking [1][1] = 5
Found 5 at position [1][1]
Search completed successfully

🔹 Why Goto is Discouraged

⚠️ Problems with Goto:

  • Spaghetti Code: Makes program flow hard to follow
  • Debugging Difficulty: Hard to trace execution path
  • Maintenance Issues: Code becomes harder to modify
  • Reduced Readability: Breaks structured programming principles

🔸 Bad Example (Avoid This):


#include <stdio.h>

int main() {
    int i = 0;
    
start:
    if(i >= 5) goto end;
    printf("%d ", i);
    i++;
    if(i == 3) goto skip;
    goto start;
    
skip:
    printf("(skipped) ");
    goto start;
    
end:
    printf("\nDone\n");
    return 0;
}

🔸 Better Alternative (Use This Instead):

// Clear, structured approach
#include <stdio.h>

int main() {
    for(int i = 0; i < 5; i++) {
        if(i == 3) {
            printf("(skipped) ");
        } else {
            printf("%d ", i);
        }
    }
    printf("\nDone\n");
    return 0;
}

🔹 Best Practices

✅ When Goto Might Be Acceptable:

  • Error handling and resource cleanup
  • Breaking out of deeply nested loops
  • State machine implementations
  • Performance-critical code (rare cases)

❌ Avoid Goto For:

  • Regular loop control (use break/continue)
  • Conditional execution (use if/else)
  • Function-like behavior (create actual functions)
  • Any case where structured alternatives exist

🎯 Golden Rule:

Use goto only when it makes code clearer and simpler, not more complex.

🧠 Test Your Knowledge

When is goto statement most appropriately used?