Un valor, muchas constantes
Una cadena else if que sigue comparando la misma variable contra constantes es un patrón con una sentencia dedicada en C:
if (choice == 1) { /* ... */ }
else if (choice == 2) { /* ... */ }
else if (choice == 3) { /* ... */ }
else { /* ... */ }
switch lo dice de forma más directa. Evalúa la expresión una vez y luego salta directo a la etiqueta que coincide.
Cambia choice y ejecútalo otra vez. La estructura hace visible de un vistazo el conjunto de valores legales, que es la razón real para preferirla aquí.
Sintaxis y las reglas de las etiquetas case
switch (expresionEntera) {
case CONSTANTE_1:
sentencias
break;
case CONSTANTE_2:
sentencias
break;
default:
sentencias
break;
}
Cuatro restricciones que C hace cumplir:
- La expresión del switch debe tener tipo entero:
int,char,short,longo unenum. Nofloat, nodoubley no una cadena. - Cada etiqueta
casedebe ser una expresión constante conocida en tiempo de compilación.case n:dondenes una variable es un error;case 3 + 4:ycase MAX:(un#defineo una constante de enum) están bien. - Dos casos no pueden tener el mismo valor. Los duplicados son un error de compilación, lo que es una red de seguridad pequeña pero genuina.
- Un caso no puede expresar un rango.
case 1 ... 5:es una extensión de GCC, no C estándar; usa unifpara los rangos.
default es opcional y puede aparecer en cualquier punto del bloque, aunque ponerlo al final es la convención casi universal. Sin un default, un valor que no coincida simplemente se salta el switch entero.
break: por qué no es opcional
Lo más sorprendente de switch en C es que las etiquetas case son destinos de salto, no cajas. En cuanto la ejecución aterriza en una etiqueta sigue adelante por cada sentencia que haya debajo —cruzando otras etiquetas case— hasta un break o la llave de cierre.
El primer switch imprime uno, dos y tres: coincidió con case 1 y luego ejecutó todo lo que venía después. El segundo imprime solo uno. Ese comportamiento se llama caída en cascada, y olvidar un break es el error clásico del switch en C: el programa queda silenciosamente mal en lugar de no compilar.
Compila con gcc -Wall -Wextra -Wimplicit-fallthrough y el compilador señala cada caso que cae en el siguiente.
El break del último caso es técnicamente redundante: el bloque termina ahí de todas formas. Escríbelo igual, para que agregar un caso nuevo debajo más adelante no cree en silencio una caída en cascada.
Caída en cascada deliberada
La caída en cascada es una virtud cuando es intencionada. Apilar etiquetas sin sentencias entre ellas es la forma corriente de decir "estos valores hacen lo mismo":
Tres etiquetas comparten un cuerpo, sin código duplicado y sin una larga condición con ||. Los compiladores no avisan de esta forma, porque no hay sentencias por las que caer.
La caída con sentencias en medio —donde el caso 1 se ejecuta y luego continúa deliberadamente hacia el caso 2— es más rara y merece un comentario explícito, ya que a quien lee hay que decirle que el break ausente fue una decisión:
switch (level) {
case 3:
printf("detallado\n");
/* fall through */
case 2:
printf("info\n");
/* fall through */
case 1:
printf("errores\n");
break;
}
/* fall through */ es el comentario que reconoce el aviso de GCC, así que además silencia el diagnóstico.
Switch sobre caracteres
Como char es un tipo entero, la clasificación de caracteres encaja de forma natural:
Fíjate en que case 'a': usa comillas simples: una constante de carácter, que no es más que el valor entero de ese carácter. case "a": sería una cadena y no compilará.
Switch sobre enums
El mejor emparejamiento en C es switch con un enum. Las etiquetas case se convierten en nombres legibles, y los compiladores pueden avisar cuando el switch no atiende a todos los enumeradores:
Dos cosas que vale la pena copiar aquí. Cada caso hace return, así que no hace falta break: un return abandona la función entera, lo que también termina el switch. Y no hay default: con -Wswitch (incluida en -Wall), dejar fuera el default hace que el compilador avise el día en que alguien agregue un quinto estado y se olvide de esta función. Un default habría escondido eso.
Declarar variables dentro de un switch
El cuerpo de un switch es un solo bloque, así que una declaración en un caso es visible —aunque no necesariamente inicializada— en los que vienen después. Saltarse una inicialización es un error en C:
switch (n) {
case 1:
int x = 10; // error en C: una etiqueta no puede preceder asi a una declaracion
printf("%d\n", x);
break;
case 2:
printf("%d\n", x); // x existe aqui, pero nunca se inicializo
break;
}
Envuelve el caso en sus propias llaves cuando necesite variables locales:
switch (n) {
case 1: {
int x = 10;
printf("%d\n", x);
break;
}
case 2:
printf("dos\n");
break;
}
¿switch o if-else?
Recurre a switch cuando todo esto sea cierto: estás probando una expresión, tiene tipo entero y la comparas contra constantes fijas. El manejo de menús, las máquinas de estados con enums, la clasificación de caracteres y el despacho de comandos son los casos canónicos. La recompensa es la legibilidad, la comprobación de valores duplicados y un compilador que puede avisar de enumeradores no atendidos.
Recurre a if-else cuando las pruebas impliquen rangos (score >= 90), valores de punto flotante, cadenas (necesitas strcmp), varias variables distintas o condiciones combinadas con && y ||. Nada de eso se puede expresar como una etiqueta case.
El rendimiento rara vez es el factor decisivo. Los compiladores convierten un switch denso en una tabla de saltos y uno disperso en comparaciones, así que con un puñado de casos las dos formas son indistinguibles. Elige la que exprese la intención.
Preguntas frecuentes
¿Cómo funciona una sentencia switch en C?
switch (expr) evalúa una expresión entera una vez, salta a la etiqueta case cuya constante coincide y se ejecuta desde ahí hasta que se topa con un break o con el final del switch. Si nada coincide, salta a default cuando existe, y si no se salta el bloque entero.
¿Por qué necesito break en un switch de C?
Porque las etiquetas case son destinos de salto, no bloques separados. Sin un break, la ejecución continúa directamente hacia las sentencias del siguiente caso; esto se llama caída en cascada (fall-through). Un break olvidado es el error más común con switch en C, y gcc -Wimplicit-fallthrough lo señalará.
¿Se puede hacer switch sobre una cadena en C?
No. Un switch de C exige una expresión entera, así que los valores int, char y enum funcionan, pero las cadenas, los decimales y los rangos no. Para ramificar según una cadena, usa strcmp en una cadena if-else, o convierte primero la cadena en un enum y haz switch sobre eso.
¿Cuándo debería usar switch en lugar de if-else en C?
Usa switch cuando compares un entero o un carácter contra una lista de constantes fijas: comandos de menú, estados de un enum, clasificación de caracteres. Usa una cadena if-else cuando las pruebas impliquen rangos, varias variables o cualquier cosa que no sea una igualdad contra una constante de tiempo de compilación.