Почему я получаю "метка может быть только частью инструкции, а декларация не является инструкцией", если у меня есть переменная, которая инициализируется после метки?
У меня есть следующий упрощенный код:
#include <stdio.h>
int main ()
{
printf("Hello ");
goto Cleanup;
Cleanup:
char *str = "World\n";
printf("%s\n", str);
}
Я получаю ошибку, потому что новая переменная объявляется после метки. Если я поместил содержимое (в основном инициализацию) после метки в блоке {}, компиляция завершится успешно.
Я думаю, что понимаю причину блокировки в случае переключения, но почему это должно быть применимо в случае метки?
Эта ошибка от компилятора gcc
2 ответа
Стандарт языка просто не допускает этого. За метками могут следовать только операторы, а объявления не считаются как операторы в C. Самый простой способ обойти это, вставив пустой оператор после вашей метки, что освобождает вас от необходимости отслеживать область действия так, как вам нужно. внутри блока.
#include <stdio.h>
int main ()
{
printf("Hello ");
goto Cleanup;
Cleanup: ; //This is an empty statement.
char *str = "World\n";
printf("%s\n", str);
}
Это причуда грамматики Си. Ярлык (Cleanup:
) не разрешается появляться непосредственно перед объявлением (например, char *str ...;
), только перед заявлением (printf(...);
). В C89 это не было большой трудностью, потому что объявления могли появляться только в самом начале блока, так что вы всегда могли немного переместить метку вниз и избежать проблемы. В C99 вы можете смешивать объявления и код, но вы все равно не можете поставить метку непосредственно перед объявлением.
Вы можете поставить точку с запятой сразу после двоеточия метки (как предлагает Ренан), чтобы там было пустое утверждение; это то, что я бы сделал в машинно-сгенерированном коде. Либо поднимите объявление в начало функции:
int main (void)
{
char *str;
printf("Hello ");
goto Cleanup;
Cleanup:
str = "World\n";
printf("%s\n", str);
return 0;
}