Muchas respuestas parecen centrarse en la capacidad de fracasar como la razón para requerir la break
declaración.
Creo que fue simplemente un error, debido en gran medida a que cuando se diseñó C no había tanta experiencia sobre cómo se usarían estas construcciones.
Peter Van der Linden expone el caso en su libro "Expert C Programming":
Analizamos las fuentes del compilador Sun C para ver con qué frecuencia se usaba la falla predeterminada. El front-end del compilador Sun ANSI C tiene 244 instrucciones de cambio, cada una de las cuales tiene un promedio de siete casos. La caída ocurre en solo el 3% de todos estos casos.
En otras palabras, el comportamiento normal del interruptor es incorrecto el 97% del tiempo. No es solo en un compilador, por el contrario, cuando se utilizó la falla en este análisis, a menudo fue para situaciones que ocurren con más frecuencia en un compilador que en otro software, por ejemplo, cuando compila operadores que pueden tener uno o dos operandos :
switch (operator->num_of_operands) {
case 2: process_operand( operator->operand_2);
/* FALLTHRU */
case 1: process_operand( operator->operand_1);
break;
}
La omisión de casos es tan ampliamente reconocida como un defecto que incluso hay una convención de comentarios especial, que se muestra arriba, que le dice a la pelusa "este es realmente uno de esos 3% de los casos en que se deseaba la falla".
Creo que fue una buena idea que C # requiriera una declaración de salto explícita al final de cada bloque de casos (al tiempo que permite que se apilen varias etiquetas de casos, siempre y cuando solo haya un bloque de declaraciones). En C # todavía puede hacer que un caso se caiga a otro, solo tiene que hacer que la caída sea explícita saltando al siguiente caso usando a goto
.
Es una lástima que Java no aprovechó la oportunidad para romper con la semántica de C.
En muchos sentidos, c es solo una interfaz limpia para modismos de ensamblaje estándar. Al escribir el control de flujo impulsado por la tabla de salto, el programador tiene la opción de caer o saltar de la "estructura de control", y un salto requiere una instrucción explícita.
Entonces, c hace lo mismo ...
fuente
NULL
. (Continúa en el siguiente comentario.)NUL
cadenas terminadas son la peor idea de la historia.DO
bucle Fortran .Para implementar el dispositivo de Duff, obviamente:
fuente
Si los casos fueron diseñados para romperse implícitamente, entonces no podrías haber sufrido un fracaso.
Si el interruptor se diseñó para explotar implícitamente después de cada caso, no tendría elección. La estructura de la caja del interruptor se diseñó de la manera que debe ser más flexible.
fuente
Las declaraciones de caso en las declaraciones de un interruptor son simplemente etiquetas.
Al encender un valor, la instrucción switch hace esencialmente un Goto a la etiqueta con el valor coincidente.
Esto significa que el descanso es necesario para evitar pasar al código bajo la siguiente etiqueta.
En cuanto a la razón por la que se implementó de esta manera, la naturaleza de caída de una declaración de cambio puede ser útil en algunos escenarios. Por ejemplo:
fuente
break
dónde se necesita. 2) Si se cambia el orden de las declaraciones de caso, el error puede resultar en la ejecución del caso incorrecto. Por lo tanto, encuentro que el manejo de C # es mucho mejor (explícitogoto case
para fallthrough, excepto para las etiquetas de mayúsculas y minúsculas vacías).break
en C #: la más simple es cuando no quierescase
hacer nada más que olvidar agregar unbreak
(tal vez te has quedado tan envuelto en el comentario explicativo o te han llamado por alguna otra tarea): la ejecución solo caerá a través de locase
siguiente. 2) alentargoto case
es alentar la codificación de "espagueti" no estructurada: puede terminar con ciclos accidentales (case A: ... goto case B; case B: ... ; goto case A;
), especialmente cuando los casos están separados en el archivo y son difíciles de asimilar en combinación. En C ++, la caída está localizada.Para permitir cosas como:
Piense en la
case
palabra clave como unagoto
etiqueta y es mucho más natural.fuente
if(0)
al final del primer caso es malo, y solo debe usarse si el objetivo es ofuscar el código.Elimina la duplicación de código cuando varios casos necesitan ejecutar el mismo código (o el mismo código en secuencia).
Dado que en el nivel del lenguaje ensamblador no le importa si se divide entre cada uno o no, no hay sobrecarga para los casos de caída, de todos modos, ¿por qué no permitirlos, ya que ofrecen ventajas significativas en ciertos casos?
fuente
Me encontré con un caso de asignación de valores en vectores a estructuras: tenía que hacerse de tal manera que si el vector de datos fuera más corto que el número de miembros de datos en la estructura, el resto de los miembros permanecerían en su valor predeterminado En ese caso, omitir
break
fue bastante útil.fuente
Como muchos han especificado aquí, es permitir que un solo bloque de código funcione para múltiples casos. Esto debería ser una ocurrencia más común para sus declaraciones de cambio que el "bloque de código por caso" que especifique en su ejemplo.
Si tiene un bloque de código por caso sin fall-through, tal vez debería considerar usar un bloque if-elseif-else, ya que eso parecería más apropiado.
fuente