В C зачем вам заявление после перехода к ярлыку? - PullRequest
30 голосов
/ 16 марта 2012

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

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

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

РЕДАКТИРОВАТЬ: Люди попросили пример, и я могу привести несколько простой пример проверки, еслимассив является подмассивом другого массива

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

Ответы [ 3 ]

38 голосов
/ 16 марта 2012

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

Существует даже пример использования оператора " empty " 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 не является обязательным в приведенной выше цитате.


4 голосов
/ 16 марта 2012

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

C обязывает это:

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

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

void foo(void)
{
    goto bla;

    bla:
    ;
 }

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

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

void foo(void)
{
    goto bla;

    bla:
    {
        int x = 42;
        printf("%d\n", x);
    }
 }
4 голосов
/ 16 марта 2012

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

label: ;

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

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

Вы можете поспорить по поводу отступа на ярлыке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...