ti-enxame.com

Declaração variável após goto Label

Hoje encontrei uma coisa interessante. Eu não sabia que não se pode declarar uma variável após um rótulo goto.

Compilando o código a seguir

#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);
}

dá erros como

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.)

Agora, qual é a lógica por trás disso? Ouvi dizer que não se pode criar variáveis ​​dentro das instruções de caso do switch. Como JUMP está dentro do mesmo escopo (o escopo da função principal, no meu caso) da instrução goto, acredito que o escopo não seja um problema aqui. Mas então, por que estou recebendo esse erro?

66
Krishnabhadra

A sintaxe simplesmente não permite. §6.8.1 Declarações rotuladas:

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

Observe que não há cláusula que permita uma "declaração rotulada". Simplesmente não faz parte do idioma.

Você pode contornar isso trivialmente, é claro, com uma declaração vazia.

JUMP:;
int a = 0;
84
Stephen Canon

Você deseja um ponto-e-vírgula após o rótulo assim:

 #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);
 }    

Em seguida, seu código é compilado corretamente para o padrão C99, com gcc -Wall -std=c99 -c krishna.c (Estou usando o GCC 4.6 no Debian/Sid/AMD64).

13
Basile Starynkevitch

Uma explicação simples, além da especificação não diz, é que o compilador espera que o código após o goto seja algo que seja compilado em uma operação da qual ele possa calcular o deslocamento e que esteja chutando porque sua declaração de variável não é uma declaração/bloco que pode ser compilado em tal deslocamento.

6
jmoreno

Minha versão do gcc (4.4) está dando esse erro de compilação:

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

. Esta mensagem de erro diz tudo.

6
Patrick B.

Se você sabe por que não pode criar variáveis ​​dentro da instrução case do switch, basicamente é a mesma razão pela qual você não pode fazer isso também. Como solução, você pode tentar isso,

#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
}
2
COD3BOY

Bem, primeiro você deve ser consistente. É LABEL ou label. Segundo, o rótulo faz parte da declaração e a declaração não responde a descrição o suficiente.

Você pode substituir LABEL: com label: ; e então é mais provável compilar.

EDIT: Agora que você editou todo o seu código, ele deve ser JUMP: substituído por JUMP: ; ;-)

2
Michael Krelin - hacker

Não é por causa da etiqueta em si, é porque já existem instruções (goto e printf). O padrão mais recente parece permitir declarações variáveis ​​em locais arbitrários, mas nem todo compilador está totalmente em conformidade com o padrão. Além disso, os identificadores diferenciam maiúsculas de minúsculas em C e seu rótulo deve ser o mesmo nos dois lugares.

1
Alexey Frunze
#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);
}
0
Jeegar Patel