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