AntonDelprado
AntonDelprado

Reputation: 847

In C why do you need a statement after a goto label?

I am writing some C code and in my code I have two nested loops. On a particular condition I want to break out of the inner loop and continue the outer loop. I tried to achieve this using a label at the end on the outer loop's code and, on the condition, goto that label. However gcc gives an error that I cannot have a label at the end of a compound statement. Why not?

Note 1: This is not a switch statement and that question has been answered elsewhere.

Note 2: This is not a question about style and whether I should or should not be using goto statements or conditional variables instead.

EDIT: People have asked for an example and I can give a slightly facile example of checking if an array is a subarray of another array

    int superArray[SUPER_SIZE] = {...}, subArray[SUB_SIZE] = {...};
    int superIndex, subIndex;

    for (superIndex=0; superIndex<SUPER_SIZE-SUB_SIZE; superIndex+=1)
    {
      for (subIndex=0; subIndex<SUB_SIZE; subIndex+=1)
        if (superArray[superIndex+subIndex] != subArray[subIndex])
          goto break_then_continue;

      // code that executes if subArray is a sub array

      break_then_continue:
    }

Upvotes: 36

Views: 19705

Answers (3)

Filip Ros&#233;en
Filip Ros&#233;en

Reputation: 63797

In the standard it's explicitly said that labels belong to a statement, therefore a simple semicolon (;) after your label can circumvent the problem you are running in to, since that counts as a statement.

There is even an example of the use of an "empty"1 statement in 6.8.3/6.

EXAMPLE 3 A null statement may also be used to carry a label just before the closing } of a compound statement

while (loop1) {
  /* ... */

  while (loop2) {
    /* ... */

    if (want_out)
      goto end_loop1;

    /* ... */
  }

  /* ... */

  end_loop1: ;
}

1 In the standard this is referred to as a null statement.


6.8.1 Labeled statements

Syntax
  1 labeled-statement:
      identifier : statement
      case constant-expression : statement
      default : statement

Notice that statement isn't optional in the above quotation.


Upvotes: 50

ouah
ouah

Reputation: 145829

The label should point to a statement.

C mandates this:

(C99, 6.8.1 Labeled statements p4) " Any statement may be preceded by a prefix that declares an identifier as a label name."

In your case you can use a null statement:

void foo(void)
{
    goto bla;

    bla:
    ;
 }

Null statements perform no operation.

Or you can also use a compound statement (a block) if you have declarations:

void foo(void)
{
    goto bla;

    bla:
    {
        int x = 42;
        printf("%d\n", x);
    }
 }

Upvotes: 6

Jonathan Leffler
Jonathan Leffler

Reputation: 753695

You simply need to write:

label: ;

The semi-colon is an empty statement. You need it because the language is defined like that; you need to go to a statement, even if it is an empty one.

    for (int i = 0; i < N; i++)
    {
        for (int j = 0; i < M; j++)
        {
            ...
            if (some_condition)
                goto continue_loop1;
            ...
        }
continue_loop1: ;
    }

You can argue about the indentation on the label.

Upvotes: 6

Related Questions