В 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:
}
Ответы
Ответ 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);
}
}