Объявление переменной после метки goto

Сегодня я нашел одну интересную вещь. Я не знал, что нельзя объявлять переменную после метки goto.

Компиляция следующего кода

#include <stdio.h>
int main() {
    int x = 5;
    goto JUMP;
    printf("x is : %d\n",x);
JUMP:
    int a = 0;  <=== giving me all sorts of error..
    printf("%d",a);
}

дает такие ошибки, как

temp.c: In function ‘main’:
temp.c:7: error: expected expression before ‘int’
temp.c:8: error: ‘a’ undeclared (first use in this function)
temp.c:8: error: (Each undeclared identifier is reported only once
temp.c:8: error: for each function it appears in.)

Теперь, какова логика этого? Я слышал, что нельзя создавать переменные внутри операторов case switch. Поскольку JUMP находится внутри той же области (область основной функции, в моем случае) инструкции goto, я считаю, что область не является проблемой здесь. Но почему, почему я получаю эту ошибку?

Ответ 1

Синтаксис просто не позволяет этого. §6.8.1 Обозначенные метки:

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

Обратите внимание, что нет предложения, которое допускает "помеченную декларацию". Он просто не является частью языка.

Вы можете тривиально обойти это, конечно, с пустой инструкцией.

JUMP:;
int a = 0;

Ответ 2

Вы хотите, чтобы точка с запятой после метки выглядела следующим образом:

 #include <stdio.h>
 int main() {
     int x = 5;
     goto JUMP;
     printf("x is : %d\n",x);
 JUMP: ;     /// semicolon for empty statement
     int a = 0; 
     printf("%d",a);
 }    

Затем ваш код правильно компилируется для стандарта C99, с gcc -Wall -std=c99 -c krishna.c (я использую GCC 4.6 на Debian/Sid/AMD64).

Ответ 3

Моя версия gcc (4.4) дает эту ошибку компиляции:

t.c:7: error: a label can only be part of a statement and a declaration is not a statement

. Это сообщение об ошибке сообщает все.

Ответ 4

Простое объяснение, отличное от спецификации, говорит, что компилятор не выполняет код после того, как goto является компилятором в операцию, которая затем может вычислять смещение, и пинает, потому что объявление переменной isn ' t оператор/блок, который он может скомпилировать в такое смещение.

Ответ 5

Хорошо, сначала вы должны быть последовательными. Это либо LABEL, либо LABEL. Во-вторых, метка является частью инструкции, и декларация не соответствует описанию.

Вы можете заменить LABEL: на label: ;, а затем его можно скомпилировать.

РЕДАКТИРОВАТЬ: Теперь, когда вы отредактировали код целиком, он должен быть JUMP: заменен на JUMP: ;; -)

Ответ 6

Если вы знаете, почему вы не можете создавать переменные внутри case-кода коммутатора, в основном это та же причина, почему вы тоже не можете это сделать. В качестве исправления вы можете попробовать это,

#include <stdio.h>
int main() {
    int x = 5;
    goto JUMP;
    printf("x is : %d\n",x);
JUMP:
    {                                              //Note this
       int a = 0;  // <=== no more error..
       printf("%d",a);
    }                                             //Note this
}

Ответ 7

Это не из-за ярлыка как такового, потому что уже есть инструкции (goto и printf). Последний стандарт, по-видимому, допускает объявления переменных в произвольных местах, но не каждый компилятор полностью соответствует стандарту. Кроме того, идентификаторы чувствительны к регистру в C, и ваша метка должна быть одинаковой в обоих местах.

Ответ 8

#include <stdio.h>
int main() {
    int x = 5;
    goto JUMP;
    printf("x is : %d\n",x);
JUMP:
    printf("Do anything after label but dont declare 
    anything. even empty statement will also work 
    because label can only be part of a statement");
    int a = 0;  
    printf("%d",a);
}