Menu

Sentencia switch en C: casos, break y caída en cascada

Cómo la sentencia switch de C elige una rama de una lista de constantes: etiquetas case, por qué importa el break, la caída en cascada deliberada y accidental, default, usar switch con chars y enums, y cuándo switch le gana a una cadena else-if.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

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, long o un enum. No float, no double y no una cadena.
  • Cada etiqueta case debe ser una expresión constante conocida en tiempo de compilación. case n: donde n es una variable es un error; case 3 + 4: y case MAX: (un #define o 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 un if para 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.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR