Подтвердить что ты не робот

В C почему вам нужно выражение после метки goto?

Я пишу код C, а в моем коде у меня два вложенных цикла. В конкретном состоянии я хочу break выйти из внутреннего цикла и continue внешнего цикла. Я попытался добиться этого, используя метку в конце кода внешнего цикла и, при условии, goto, что метка. Однако gcc дает ошибку, что я не могу иметь метку в конце составного оператора. Почему бы и нет?

Примечание 1: это не оператор switch, и на этот вопрос был дан ответ в другом месте.

Примечание 2: Это не вопрос о стиле и должен ли я использовать или не использовать операторы goto или условные переменные.

EDIT: люди попросили пример, и я могу дать слегка облегченный пример проверки того, является ли массив подмассивом другого массива

    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:
    }
4b9b3361

Ответ 1

В стандарте он явно сказал, что метки принадлежат оператору, поэтому простая точка с запятой (;) после того, как ваш ярлык может обойти проблему, в которой вы работаете, поскольку это считается выражением.

Существует даже пример использования "пустого" оператора 1 в 6.8.3/6.

ПРИМЕР 3 Нулевой оператор также может использоваться для переноса метки только перед закрытием} составного оператора

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

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

    if (want_out)
      goto end_loop1;

    /* ... */
  }

  /* ... */

  end_loop1: ;
}

1 В стандарте это называется null statement.


6.8.1 Обозначенные утверждения

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

Обратите внимание, что statement не является обязательным в приведенной выше цитате.


Ответ 2

Вам просто нужно написать:

label: ;

Полу-двоеточие - это пустой оператор. Вам это нужно, потому что язык определен таким образом; вам нужно перейти к утверждению, даже если оно пустое.

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

Вы можете спорить о отступе на этикетке.

Ответ 3

Метка должна указывать на оператор.

C обязывает:

(C99, 6.8.1 Обозначенные операторы p4) "Любой оператор может предшествовать префикс, который объявляет идентификатор как имя метки."

В вашем случае вы можете использовать оператор null:

void foo(void)
{
    goto bla;

    bla:
    ;
 }

Нулевые утверждения не выполняют никаких операций.

Или вы также можете использовать составной оператор (блок), если у вас есть объявления:

void foo(void)
{
    goto bla;

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