Declaración de variables después de la etiqueta goto


Hoy he encontrado una cosa interesante. No sabía que uno no puede declarar una variable después de una etiqueta goto.

Compilando el siguiente código

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

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

Ahora, ¿cuál es la lógica detrás de eso? He oído que uno no puede crear variables dentro de las sentencias case de switch. Dado que JUMP está dentro del mismo ámbito (el ámbito de la función principal, en mi caso) de la sentencia goto, creo que el ámbito no es un problema aquí. Pero entonces, ¿por qué estoy obtener este error?

Author: svick, 2011-12-05

8 answers

La sintaxis simplemente no lo permite. §6.8.1 Declaraciones etiquetadas:

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

Tenga en cuenta que no hay ninguna cláusula que permita una "declaración etiquetada". No es parte del lenguaje.

Puede trabajar trivialmente alrededor de esto, por supuesto, con una declaración vacía.

JUMP:;
int a = 0;
 76
Author: Stephen Canon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-05 11:19:45

Quieres un punto y coma después de la etiqueta como esta:

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

Entonces su código se compila correctamente para el estándar C99, con gcc -Wall -std=c99 -c krishna.c (estoy usando GCC 4.6 en Debian/Sid/AMD64).

 11
Author: Basile Starynkevitch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-05 11:21:06

Mi versión de gcc (4.4) está dando este error de compilación:

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

. Este mensaje de error lo dice todo.

 6
Author: Patrick B.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-05 11:14:23

Una explicación simple, aparte de la especificación dice que no, es que el compilador está exepectando el código después del goto para que sea algo que compila en una operación de la que luego puede calcular el desplazamiento, y está pateando porque su declaración de variable no es una declaración/bloque que pueda compilar en dicho desplazamiento.

 6
Author: jmoreno,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-05 19:11:25

Bueno, primero debes ser consistente. Es LABEL o label. En segundo lugar, la etiqueta es una parte de la declaración y la declaración no responde lo suficiente a la descripción.

Puede reemplazar LABEL: con label: ; y luego es más probable que compile.

EDITAR: Ahora que editó su código por todas partes, debería ser JUMP: reemplazado con JUMP: ; ;-)

 2
Author: Michael Krelin - hacker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-05 11:13:41

Si sabes por qué no puedes crear variables dentro de la sentencia case de switch, básicamente es la misma razón por la que no puedes hacer esto también. Como solución, puedes probar esto,

#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
Author: COD3BOY,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-05 11:35:38

No es por la etiqueta per se, es porque ya hay sentencias (goto e printf). El último estándar parece permitir declaraciones de variables en lugares arbitrarios, pero no todos los compiladores se ajustan completamente al estándar. Además, los identificadores distinguen entre mayúsculas y minúsculas en C y la etiqueta debe ser la misma en ambos lugares.

 1
Author: Alexey Frunze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-05 11:15:24
#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
Author: Jeegar Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-05 12:23:34