2

To play around with the goto statement, I've rewritten a while loop in a more assembly-style loop:

// while
int i=0;
while (i++<10)
    printf("%d...", i);
// asm-ish
loop:
    i++;
    printf("%d...", i);
    if (i<10)
        goto loop;
loop_exit:
    return 0;

Outside of a sort of academic exercise, are there any real-world/useful examples of how the goto statement can be used? Or is this basically a vestigial part of c that isn't used.

Here's an example of a code file that makes extensive use of it: https://github.com/postgres/postgres/blob/ca3b37487be333a1d241dab1bbdd17a211a88f43/src/port/snprintf.c.

I suppose one thing I can think of is getting out of deep-nesting without having to use a bunch of continue/breaks, but that's about it.

samuelbrody1249
  • 4,379
  • 1
  • 15
  • 58
  • 4
    This is really an opinions based question and is thus not very suitable as a Stack Overflow question. One opinion: `goto` is commonly used to jump to the end of a function from error paths to do common clean up and exit. – kaylum Jan 25 '21 at 22:22
  • 1
    @kaylum I suppose, though I'm a beginner in C and curious how it is used. I'm not just looking for an opinion of "oh it's great" or "oh it's bad", but actually someone who has used C for more than three weeks of how it can be used effectively (if it can be). – samuelbrody1249 Jan 25 '21 at 22:23
  • 2
    [CPython](https://github.com/python/cpython) (the main implementation of Python) makes fairly extensive use of `goto`. If you flip around through the code, you may be able to see why they have it set up like they do. – Carcigenicate Jan 25 '21 at 22:26
  • @Carcigenicate cool thanks for sharing. Is that considered a valid use of it or poor programming? – samuelbrody1249 Jan 25 '21 at 22:28
  • A more or less legitimate use which is acceptable on *almost* anyone, is breaking out of nested loops to a cleanup/error handling code right before returning from a function. – Eugene Sh. Jan 25 '21 at 22:28
  • 2
    There are some dupes around here (e.g. https://stackoverflow.com/questions/245742/examples-of-good-gotos-in-c-or-c or https://stackoverflow.com/questions/46586/goto-still-considered-harmful) on the subject. – Bob__ Jan 25 '21 at 22:29
  • 1
    Here are two more related threads: [1](https://stackoverflow.com/q/24451/12149471) [2](https://codereview.stackexchange.com/q/250656/235181) – Andreas Wenzel Jan 25 '21 at 23:08

1 Answers1

3

While you can use goto in this way, it's generally considered bad style since the language has other constructs like while that do the same thing in a "cleaner" fashion.

Once place where it does make sense to use goto is to jump forward for error handling situations. For example, this:

void foo()
{
    char *p1 = NULL, *p2 = NULL, *p3 = NULL, *p4 = NULL;
    
    p1 = malloc(1000);
    if (!p1) {
        perror("malloc failed");
        return;
    }
    p2 = malloc(1000);
    if (!p2) {
        perror("malloc failed");
        free(p1);
        return;
    }
    p3 = malloc(1000);
    if (!p3) {
        perror("malloc failed");
        free(p2);
        free(p1);
        return;
    }
    p4 = malloc(1000);
    if (!p4) {
        perror("malloc failed");
        free(p3);
        free(p2);
        free(p1);
        return;
    }

    // Do something with p1, p2, p3, p4

    free(p4);
    free(p3);
    free(p2);
    free(p1);
}

Can be translated to this:

void foo()
{
    char *p1 = NULL, *p2 = NULL, *p3 = NULL, *p4 = NULL;
    
    p1 = malloc(1000);
    if (!p1) {
        perror("malloc failed");
        goto err0;
    }
    p2 = malloc(1000);
    if (!p2) {
        perror("malloc failed");
        goto err1;
    }
    p3 = malloc(1000);
    if (!p3) {
        perror("malloc failed");
        goto err2;
    }
    p4 = malloc(1000);
    if (!p4) {
        perror("malloc failed");
        goto err3;
    }

    // Do something with p1, p2, p3, p4

    free(p4);
err3:
    free(p3);
err2:
    free(p2);
err1:
    free(p1);
err0:
    return;
}

This puts all of the cleanup code in one place.

dbush
  • 205,898
  • 23
  • 218
  • 273