que corrieron a este problema, y un día decidió que se hundía en ella.
El corto no respuesta pero solución pragmática:
Una manera de evitar este "problema" es utilizar un punto y coma, ;
, justo después de los dos puntos de una declaración case ...:
. Por ejemplo, utilizando el ejemplo que nos ha facilitado, puede ser "fijo", por lo que se compila y se comporta como lo haría intuitivamente esperar que:
case 1:; // <- Note semi-colon.
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
La respuesta larga:
Un poco de historia: Anteriormente, C sólo le permitió declarar las variables "bloquear local" al comienzo de un bloque, que fue seguido por varias declaraciones. C99 cambió las cosas para que pudieras mezclar libremente las declaraciones y declaraciones de variables.
En el contexto de la gramática C99 BNF, una declaración de variable es declaration
, y una instrucción es statement
. Un statement
significa varias cosas, una de ellas se conoce como compound-statement
, que es el familiar bloque { ... }
.La parte ...
se define en términos generales como zero or more
block-items
, con un block-item
ser vagamente definido como either a
declaration
or a
statement
.
El problema radica en la forma en que un labeled-statement
(una etiqueta Goto, etiqueta de la caja, o default:
, esencialmente los ...:
declaraciones) se define, que es vagamente definido ...: zero or more
statements
. No es, como se podría esperar intuitivamente, zero or more
statements
or
declarations
. El uso de un ;
justo después de labeled-statement
s :
esencialmente termina el zero or more
statements
parte de un labeled-statement
. Esto hace que la gramática vuelva a la definición compound-statement
, que permite que la siguiente "declaración" sea statement
o declaration
.
No he investigado si esta es una visión involuntaria del lenguaje C99 (en términos prácticos, un error en el estándar C99), o si esta es una concesión pragmática a las complejidades de escribir gramáticas del lenguaje . Si no está familiarizado con la escritura de gramáticas, notará que la explicación anterior permite la recursión: A labeled-statement
puede coincidir con case 1: case 2: case 3:
. En términos excesivamente simplistas (1)
, algunos tipos de recursión gramatical son simples e "inequívocos", mientras que otros son complejos y "ambiguos". Para simplificar, la mayoría de las herramientas de lenguaje solo manejarán el caso en el que cualquier ambigüedad debe resolverse determinísticamente mirando nada más que "el siguiente token". Menciono esto solo porque si bien esto podría parecer intuitivamente como una deficiencia en la especificación C99, puede haber razones convincentes y no obvias por las que esto existe ... y no me he molestado en investigar más sobre el tema para averiguarlo. de cualquier manera.
(1)
Esto no pretende ser una descripción técnicamente precisa, sino una aproximación razonable para aquellos que no están familiarizados con los problemas involucrados.
EDIT:
La solución que dio obras en la "mayoría" de los casos (casos son "usos", no switch
case
s), pero no fallar en un caso: Esto no funcionará cuando el declaración declara un C99 variable length array
, como case 1:; void *ptrs[count];
Esto se debe a que en C99 es un error "saltar" la declaración de un C99 VLA que está en el mismo alcance léxico donde tuvo lugar el salto. En estos casos, debe usar case 1: { void *ptrs[count]; }
. En este caso, el alcance del ptrs
VLA finaliza en el cierre }
. Esto es más complicado de lo que parece ya que el siguiente es el código C perfectamente legal, aunque a primera vista se podría pensar intuitivamente que no es:
switch(3){
case 0:
printf("case 0\n");
break;
case 1:;
int *ip = NULL;
printf("case 1\n");
break;
case 2:
{
int ia[6];
printf("case 2\n");
break;
case 3:
printf("case 3\n");
break;
default:
printf("default\n");
}
}
Esto compila, y cuando se ejecuta, impresiones case 3
.
Ver también: Wikipedia: Duffs Device
+1 Sin embargo, puede hacerlo si crea un alcance anidado usando {...} para envolver las declaraciones de una etiqueta de caso. –