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-statementoptC++17condition)statement

init-statement:
expression-statement
simple-declaration

condition:
expression
attribute-specifier-seqopt decl-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 da instrução switch consiste em uma série de etiquetas case e uma etiqueta optopcionaldefault. 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 caseconstant-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 case'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 case'a' minúsculo, 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.

Confira também

Instruções de seleção
Palavras-chave