36

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:
    }
1
  • 3
    Can you provide a small program that reproduces the error message you get? Commented Mar 16, 2012 at 2:10

3 Answers 3

50

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.


Sign up to request clarification or add additional context in comments.

6 Comments

+1 Great answer. Love the example taken straight from the standard.
Thanks for the great response. I was looking for why gcc works in the way it does not how to get around it. However your response tends to indicate that it is simply the way c is written. This being largely a legacy from when c compilation was only a minor abstraction of assembly code.
@AntonDelprado It's actually pretty simple, goto will place label before command/expression and if there is no such thing, there is nowhere to jump. That empty statement is used so this is possible. like this you jump on some harmless equivalent of NOP (no operation) assembly function.
Wow, that means a switch statement is just a bunch of gotos. I guess it's obvious, but I never considered it. Anyone who dogmatically denounces goto--and wants to remain consistent--should also bemoan using switch. Either that or be content with using goto as a superbreak;
@jdk1.0 Even worse, switch is a computed goto (i.e. one where the target is dynamic). :-)
|
6

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.

1 Comment

Also note that a declaration, even with an initialization, is not a statement that can be labelled: label1: int x = function(y, z); is not valid.
6

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);
    }
 }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.