Tengo una situación en la que me gustaría que dos casos en una declaración de cambio de C++ caigan en un tercer caso. Específicamente, el segundo caso caería en el tercer caso, y el primer caso también caería en el tercer caso sin pasar por el segundo caso.
¡Tuve una idea tonta, la probé y funcionó! Envolví el segundo caso en un if (0) { ... } . Se parece a esto:
#ifdef __cplusplus # include <cstdio> #else # include <stdio.h> #endif int main(void) { for (int i = 0; i < 3; i++) { printf("%d: ", i); switch (i) { case 0: putchar('a'); // @fallthrough@ if (0) { // fall past all of case 1 (!) case 1: putchar('b'); // @fallthrough@ } case 2: putchar('c'); break; } putchar('\n'); } return 0; }Cuando lo ejecuto, obtengo el resultado deseado:
0: ac 1: bc 2: cLo probé tanto en C como en C++ (ambos con sonido metálico) e hizo lo mismo.
Mis preguntas son: ¿Es válido C/C++? ¿Se supone que debe hacer lo que hace?
Sí, se supone que esto funciona. Las etiquetas de caso para una declaración de cambio en C son casi exactamente como las etiquetas goto (con algunas advertencias sobre cómo funcionan con declaraciones de cambio anidadas). En particular, no definen bloques por sí mismos para las declaraciones que usted piensa que están "dentro del caso", y puede usarlos para saltar al medio de un bloque tal como lo haría con un goto. Al saltar a la mitad de un bloque, se aplican las mismas advertencias que con goto con respecto a saltar sobre la inicialización de variables, etc.
Dicho esto, en la práctica probablemente sea más claro escribir esto con una instrucción goto, como en:
switch (i) { case 0: putchar('a'); goto case2; case 1: putchar('b'); // @fallthrough@ case2: case 2: putchar('c'); break; }Sí, esto está permitido, y hace lo que quieres. Para una declaración de switch , el estándar C++ dice :
Las etiquetas de mayúsculas y minúsculas en sí mismas no alteran el flujo de control, que continúa sin impedimentos a través de dichas etiquetas. Para salir de un interruptor, vea descanso.
[Nota 1: por lo general, la subdeclaración que es objeto de un cambio es compuesta y las etiquetas de mayúsculas y minúsculas aparecen en las declaraciones de nivel superior contenidas dentro de la subdeclaración (compuesta), pero esto no es obligatorio. Las declaraciones pueden aparecer en la subdeclaración de una declaración de cambio. - nota final]
Entonces, cuando se evalúa la declaración if , el flujo de control procede de acuerdo con las reglas de una declaración if , independientemente de las etiquetas de caso intermedias.
Como han mencionado otras respuestas, esto está técnicamente permitido por el estándar, pero es muy confuso y poco claro para los futuros lectores del código.
Esta es la razón por la que las sentencias switch ... case generalmente deben escribirse con llamadas a funciones y no con mucho código en línea.
switch(i) { case 0: do_zero_case(); do_general_stuff(); break; case 1: do_one_case(); do_general_stuff(); break; case 2: do_general_stuff(); break; default: do_default_not_zero_not_one_not_general_stuff(); break; }