Instrução switch
(C++)
Permite a seleção entre várias seções de código, dependendo do valor de uma expressão integral.
Sintaxe
selection-statement
:
switch
(
init-statement
optC++17condition
)
statement
init-statement
:
expression-statement
simple-declaration
condition
:
expression
attribute-specifier-seq
optdecl-specifier-seq
declarator
brace-or-equal-initializer
labeled-statement
:
case
constant-expression
:
statement
default
:
statement
Comentários
Uma instrução switch
faz com que o controle seja transferido para um labeled-statement
no corpo da instrução, dependendo do valor de condition
.
O condition
deve ter um tipo integral ou ser um tipo de classe que tem uma conversão não ambígua em um tipo integral. A promoção integral ocorre conforme descrito nas Conversões padrão.
O corpo do comando switch
consiste em uma série de rótulos case
e um rótulo default
opcional. A labeled-statement
é uma dessas etiquetas e as instruções a seguir. As instruções rotuladas não são requisitos sintáticos, mas a instrução switch
fica sem sentido sem elas. Dois valores constant-expression
em instruções case
não podem avaliar para o mesmo valor. A etiqueta default
pode aparecer apenas uma vez. A instrução default
geralmente é colocada no final, mas pode aparecer em qualquer lugar no corpo da instrução switch
. Uma etiqueta case
ou default
pode ser exibida apenas dentro de uma instrução switch
.
A etiqueta constant-expression
em cada etiqueta case
é convertida em um valor constante do mesmo tipo que condition
. Então, é comparada a condition
quanto à igualdade. O controle passa para a primeira instrução após o valor case
constant-expression
que corresponde ao valor de condition
. O comportamento resultante é mostrado na tabela a seguir.
Comportamento da instrução switch
Condição | Ação |
---|---|
O valor convertido corresponde ao da expressão de controle promovida. | O controle é transferido para a instrução após esse rótulo. |
Nenhuma das constantes corresponde às constantes nas etiquetas case ; uma etiqueta default está presente. |
O controle é transferido para a etiqueta default . |
Nenhuma das constantes corresponde às constantes nas etiquetas case ; nenhuma etiqueta default está presente. |
O controle é transferido para a instrução após a instrução switch . |
Se uma expressão correspondente for encontrada, a execução poderá continuar por meio de etiquetas case
ou default
posteriores. A instrução break
é usada para parar a execução e transferir o controle para a instrução após a instrução switch
. Sem uma instrução break
, cada instrução da estado da etiqueta case
correspondente até o fim de switch
, incluindo default
, é executada. Por exemplo:
// switch_statement1.cpp
#include <stdio.h>
int main() {
const char *buffer = "Any character stream";
int uppercase_A, lowercase_a, other;
char c;
uppercase_A = lowercase_a = other = 0;
while ( c = *buffer++ ) // Walks buffer until NULL
{
switch ( c )
{
case 'A':
uppercase_A++;
break;
case 'a':
lowercase_a++;
break;
default:
other++;
}
}
printf_s( "\nUppercase A: %d\nLowercase a: %d\nTotal: %d\n",
uppercase_A, lowercase_a, (uppercase_A + lowercase_a + other) );
}
No exemplo acima, uppercase_A
será incrementado se c
for 'A'
maiúsculo. A instrução break
após uppercase_A++
termina a execução do corpo da instrução switch
e passa o controle para o loop while
. Sem a instruçãobreak
, a execução faria "fall-through" para a próxima instrução etiquetada, de modo que lowercase_a
e other
também seriam incrementadas. A instrução break
para case 'a'
cumpre finalidade semelhante. Se c
for uma letra minúscula, 'a'
, lowercase_a
será incrementado e a instrução break
terminará o corpo da instrução switch
. Se c
não for um 'a'
ou 'A'
, a instrução default
será executada.
Visual Studio 2017 e posteriores (disponível no modo /std:c++17
e posteriores): o atributo [[fallthrough]]
é especificado no padrão C++17. Você só pode usá-lo em uma instrução switch
. É uma dica para o compilador, ou qualquer pessoa que lê o código, de que o comportamento de fall-through é intencional. O compilador do Microsoft C++ atualmente não avisa sobre o comportamento de fallthrough, portanto, esse atributo não tem efeito no comportamento do compilador. No exemplo, o atributo é aplicado a uma instrução vazia dentro da instrução rotulada não terminada. Em outras palavras, o ponto e vírgula é necessário.
int main()
{
int n = 5;
switch (n)
{
case 1:
a();
break;
case 2:
b();
d();
[[fallthrough]]; // I meant to do this!
case 3:
c();
break;
default:
d();
break;
}
return 0;
}
Visual Studio 2017 versão 15.3 e posteriores (disponível no modo /std:c++17
e posteriores): uma instrução switch
pode ter uma cláusula init-statement
, que termina com um ponto e vírgula. Ele introduz e inicializa uma variável cujo escopo está limitado ao bloco da instrução switch
:
switch (Gadget gadget(args); auto s = gadget.get_status())
{
case status::good:
gadget.zip();
break;
case status::bad:
throw BadGadget();
};
Um bloco interno de uma instrução switch
pode conter definições com inicializações, desde que elas sejam acessíveis, isto é, não sejam ignoradas por todos os caminhos de execução possíveis. Os nomes introduzidos por meio dessas declarações têm escopo local. Por exemplo:
// switch_statement2.cpp
// C2360 expected
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
switch( tolower( *argv[1] ) )
{
// Error. Unreachable declaration.
char szChEntered[] = "Character entered was: ";
case 'a' :
{
// Declaration of szChEntered OK. Local scope.
char szChEntered[] = "Character entered was: ";
cout << szChEntered << "a\n";
}
break;
case 'b' :
// Value of szChEntered undefined.
cout << szChEntered << "b\n";
break;
default:
// Value of szChEntered undefined.
cout << szChEntered << "neither a nor b\n";
break;
}
}
Uma instrução switch
pode estar aninhada. Quando aninhadas, as etiquetas case
ou default
se associam à instrução switch
mais próxima que as inclui.
Comportamento específico da Microsoft
O Microsoft C++ não limita o número de valores case
em uma instrução switch
. O número é limitado somente pela memória disponível.