switch
statement
Transfiere el control a una de varias sentencias, dependiendo del valor de una condición.
Contenidos |
Sintaxis
attr
(opcional)
switch
(
init-statement
(opcional)
condition
)
statement
|
|||||||||
| attr | - | (desde C++11) cualquier número de atributos | ||
| init-statement | - |
(desde C++17)
cualquiera de los siguientes:
Nótese que cualquier init-statement debe terminar con un punto y coma. Por esto se describe informalmente como una expresión o una declaración seguida de un punto y coma. |
||
| condition | - | una condición | ||
| statement | - | una sentencia (típicamente una sentencia compuesta) |
Condición
Una condición puede ser una expresión o una declaración simple .
|
(since C++26) |
- Si puede resolverse sintácticamente como una expresión, se trata como una expresión. De lo contrario, se trata como una declaración que no es una declaración de enlace estructurado (desde C++26) .
Cuando el control alcanza la condición, la condición producirá un valor, que se utiliza para determinar a qué etiqueta irá el control.
Expresión
Si condition es una expresión, el valor que produce es el valor de la expresión.
Declaración
Si condition es una declaración simple, el valor que produce es el valor de la variable de decisión (ver más abajo).
Declaración de enlace no estructurado
La declaración tiene las siguientes restricciones:
- Se ajusta sintácticamente a la siguiente forma:
|
(hasta C++11) |
|
(desde C++11) |
- El declarador no puede especificar una function o un array .
- La secuencia de especificadores de tipo (hasta C++11) secuencia de especificadores de declaración solo puede contener especificadores de tipo y constexpr , y (desde C++11) no puede definir una class o una enumeration .
La variable de decisión de la declaración es la variable declarada.
Declaración de enlace estructuradoLa declaración tiene las siguientes restricciones:
La variable de decisión de la declaración es la variable inventada e introducida por la declaración . |
(desde C++26) |
Tipo
condition solo puede producir los siguientes tipos:
- tipos integrales
- tipos de enumeración
- tipos de clase
Si el valor producido es de un tipo clase, se convierte implícitamente contextualmente a un tipo integral o de enumeración.
Si el tipo (posiblemente convertido) está sujeto a integral promotions , el valor resultante se convierte al tipo promocionado.
Etiquetas
Cualquier sentencia dentro de la switch puede ser etiquetada con una o más de las siguientes etiquetas:
attr
(opcional)
case
expresión-constante
:
|
(1) | ||||||||
attr
(opcional)
default:
|
(2) | ||||||||
| attr | - | (since C++11) cualquier número de atributos |
| constant-expression | - | una expresión constante convertida del tipo ajustado de la condición switch |
Una
case
o
default
label está asociada con la instrucción
switch
más interna que la contiene.
Si se satisface cualquiera de las siguientes condiciones, el programa está mal formado:
- Una switch statement está asociada con múltiples case labels cuyas constant-expression s tienen el mismo valor después de conversiones.
- Una switch statement está asociada con múltiples default labels.
Transferencia de flujo de control
Cuando la condición de una sentencia switch produce un valor (posiblemente convertido):
- Si una de las constantes de etiqueta case asociadas tiene el mismo valor, el control se transfiere a la sentencia etiquetada por la coincidencia de etiqueta case .
- De lo contrario, si hay una etiqueta default asociada, el control se transfiere a la sentencia etiquetada por la etiqueta default .
- De lo contrario, ninguna de las sentencias en la sentencia switch será ejecutada.
case y default las etiquetas en sí mismas no alteran el flujo de control. Para salir de una switch declaración desde el medio, consulte break declaraciones .
Los compiladores pueden emitir advertencias sobre fallthrough (alcanzar la siguiente
case
o
default
sin un
break
)
a menos que el atributo
[[
fallthrough
]]
aparezca inmediatamente antes de la etiqueta
case
para indicar que el fallthrough es intencional
(desde C++17)
.
|
switch sentencias con inicializadorSi se utiliza init-statement , la sentencia switch equivale a
Excepto que los nombres declarados por el init-statement (si init-statement es una declaración) y los nombres declarados por condition (si condition es una declaración) están en el mismo ámbito, que también es el ámbito de statement . |
(desde C++17) | |||||||||||||||||||||||
Notas
Debido a que la transferencia de control no está permitida para entrar al ámbito de una variable, si una declaración es encontrada dentro de la statement , debe tener ámbito en su propio statement compuesto:
Palabras clave
Ejemplo
El siguiente código muestra varios casos de uso de la sentencia switch :
#include <iostream> int main() { const int i = 2; switch (i) { case 1: std::cout << '1'; case 2: // la ejecución comienza en esta etiqueta case std::cout << '2'; case 3: std::cout << '3'; [[fallthrough]]; // atributo C++17 para silenciar la advertencia sobre fallthrough case 5: std::cout << "45"; break; // se termina la ejecución de las sentencias posteriores case 6: std::cout << '6'; } std::cout << '\n'; switch (i) { case 4: std::cout << 'a'; default: std::cout << 'd'; // no hay expresiones constantes aplicables // por lo tanto se ejecuta default } std::cout << '\n'; switch (i) { case 4: std::cout << 'a'; // no se ejecuta nada } // cuando se utilizan enumeraciones en una sentencia switch, muchos compiladores // emiten advertencias si uno de los enumeradores no es manejado enum color { RED, GREEN, BLUE }; switch (RED) { case RED: std::cout << "red\n"; break; case GREEN: std::cout << "green\n"; break; case BLUE: std::cout << "blue\n"; break; } // la sintaxis de init-statement de C++17 puede ser útil cuando no hay // conversión implícita a tipo integral o de enumeración struct Device { enum State { SLEEP, READY, BAD }; auto state() const { return m_state; } /* ... */ private: State m_state{}; }; switch (auto dev = Device{}; dev.state()) { case Device::SLEEP: /* ... */ break; case Device::READY: /* ... */ break; case Device::BAD: /* ... */ break; } // ejemplos patológicos // la sentencia no tiene que ser una sentencia compuesta switch (0) std::cout << "this does nothing\n"; // las etiquetas tampoco requieren una sentencia compuesta switch (int n = 1) case 0: case 1: std::cout << n << '\n'; }
Salida:
2345 d red 1
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| CWG 1767 | C++98 |
condition
s de tipos que no están sujetos a
promoción integral no podían promoverse |
no promover
condition s de estos tipos |
| CWG 2629 | C++98 | condition podría ser una declaración de una variable de punto flotante | prohibido |
Véase también
|
Documentación de C
para
switch
|
Enlaces externos
| 1. | Desenrollado de bucles usando el Dispositivo de Duff |
| 2. | El dispositivo de Duff puede usarse para implementar corrutinas en C/C++ |