Having Fun with goto

Difficulty: ★ ★ ★ ☆

Among the C language’s slender assortment of keywords you find goto. It’s a branching statement, which can be used to loop or to escape from some ugly programming knot. Regardless, you’re told early on in your C language education that you must avoid this keyword at all costs! That is, unless you want to try this month’s exercise.

As a review, the goto keyword branches program execution to a label. Labels are things you probably don’t use often in C programming, though they do appear inside a switch-case structure. The label is the only thing on a line of text. It’s an identifier (named like a variable) immediately followed by a colon:

there:

This label serves as a target for the goto statement:

goto there;

The goto statement ends with a semicolon, which is something you might forget (or use a colon instead). After encountering the above statement, program flow jumps to the there label and continues execution. It’s this aspect of goto that requires the warning: Using goto to hippity-hop around your source code makes the code difficult to read and lends itself to other unnecessary problems. The descriptive term is “spaghetti code,” which isn’t flattering. Even so, goto is a valid keyword and has never been deprecated.

Consider the following code, which demonstrates a nested loop:

2025_11_01-Exercise.c

#include <stdio.h>

int main()
{
    int a;
    char b;

    for( a=0; a<10; a++ )
    {
        for( b='A'; b<'K'; b++ )
        {
            printf("%c%d  ",b,a);
        }
        putchar('\n');
    }

    return 0;
}

Like most nested loops I can think of, this one processes a matrix, rows of numbers and letters, all neatly presented in a grid:

A0  B0  C0  D0  E0  F0  G0  H0  I0  J0  
A1  B1  C1  D1  E1  F1  G1  H1  I1  J1  
A2  B2  C2  D2  E2  F2  G2  H2  I2  J2  
A3  B3  C3  D3  E3  F3  G3  H3  I3  J3  
A4  B4  C4  D4  E4  F4  G4  H4  I4  J4  
A5  B5  C5  D5  E5  F5  G5  H5  I5  J5  
A6  B6  C6  D6  E6  F6  G6  H6  I6  J6  
A7  B7  C7  D7  E7  F7  G7  H7  I7  J7  
A8  B8  C8  D8  E8  F8  G8  H8  I8  J8  
A9  B9  C9  D9  E9  F9  G9  H9  I9  J9  

Your task for this month’s Exercise is to generate identical output by using goto statements and labels instead of nested for loops.

The difficulty level for this challenge to three out of four stars, which isn’t because the program itself is tough to code. No, the problem is that your C programming brain isn’t trained to think of goto as a way to accomplish this task. Yes, even though the solution presents as C code, it’s not an approach any C programmer would ever consider!

Have fun with this one! I know that I did. I marveled at my solution, not because it was anything that would win an award, but that it was entirely possible using a weirdo approach to C coding that I’ve never considered.

5 thoughts on “Having Fun with goto

  1. Knowing assembly language can be useful from time to time, I guess… hereʼs what I came up with:

    #include <stdio.h>

    int main (void)
    { int a = 0; char b;

    next_row:
      b = 'A';

    print_loop:
      printf ("%c%d ", b, a);
      if (++b < 'K') goto print_loop;

      putchar ('\n');
      if (++a < 10) goto next_row;

      return (0);
    }

  2. “that you must avoid this keyword at all costs!”

    While itʼs true that newcomers to programming are constantly told this, itʼs true also that in C the use of goto is not that strictly prohibited, as it has a use thatʼs quite well-established in the community: error handling.

    The C programming language may not have exceptions, but one can use gotos to ensure resource cleanup:

    int do_something (void)
    { int retval = -1;

      /* Acquire r1, r2, r3: */
      r1 = acquire_resource_1 ();
      if (!r1) goto ret_status;

      r2 = acquire_resource_2 ();
      if (!r2) goto cleanup_resource_1;

      r3 = acquire_resource_3 ();
      if (!r3) goto cleanup_resource_2;

      {
        /* Do some work with r1, r2 and r3 */
      }

      retval = 0; /* everything went OK */
    cleanup_resource_3:
      release_resource_3 ();
      /* fall through */
    cleanup_resource_2:
      release_resource_2 ();
    cleanup_resource_1:
      release_resource_1 ();
    ret_status:
      return (retval);
    }

    For error handling, this is an established code pattern in C. For example, Linus Torvalds linux GitHub tree currently contains more than 200,000 such gotos.

  3. I had not idea about Linux! That’s amazing.

    Thank you, as always, for your insight – and for the solution! What’s your thoughts about using goto versus using longjmp()?

  4. My thoughts on this are as follows: there was a time when people thought about (mis)using setjmp()/longjmp() for a kind of “poor manʼs exception handling”.

    For example, an earlier release of the lcc (“Little C Compiler”), as described in the book A Retargetable C Compiler: Design and Implementation by David Hanson and Christopher Fraser relied on these functions—together with some preprocessor magic—to implement TRY and CATCH macros. (Nowadays, there seems to be no trace left of this in lccʼs source code.)

    This, as is well known, with a catch: while longjmp() correctly unwinds the stack, restores the stack pointer to its former value, local variables (the compiler decided to keep in CPU registers) will most likely have incorrect values after returning to an earlier point in the program, i.e. only volatile variables are safe to access after longjmp().

    Because of this it’s a very rare thing for me to use these functions, if at all. They can be useful if one wants to return from a deeply nested stack, but otherwise I prefer to stick to goto+return.

    If the thought of how nice a kind of exception handling mechanism would be comes up too often while developing a solution to a problem, then C++ may be a better fit in such situations.

Leave a Reply