O Comando Switch (Case): Um Guia Visual e Prático
Aprenda o comando switch de forma visual: como ele pula direto para um caso, break e a queda para o próximo caso, casos empilhados, enums e os avisos do compilador, máquinas de estados, o que o C++ não aceita, uma medição real e exercícios com respostas.

Nesta página
Menus, controles de jogo, dias da semana, semáforos: muitas decisões se resumem a "olhe este valor e faça algo diferente para cada possibilidade". Você poderia escrever isso como uma cadeia comprida de if / else if. O comando switch é uma ferramenta mais arrumada, feita exatamente para esse trabalho.
Neste guia você vai ver como um switch escolhe o seu caso, a famosa pegadinha do break (e quando cair no próximo caso é até útil), como enums e avisos do compilador protegem você, como montar uma pequena máquina de estados e o que o C++ não deixa você usar num switch. Tem também uma medição real e, no fim, exercícios com respostas.
Um valor, muitos caminhos possíveis
Uma cadeia if/else faz as suas perguntas uma de cada vez, de cima para baixo. Um switch olha o valor uma vez e vai direto para o caso (case) que bate:

Aqui está um switch que diz o nome do dia da semana:
1#include <iostream>
2
3int main() {
4 int dia;
5 std::cout << "Dia da semana (1-7): ";
6 std::cin >> dia;
7
8 switch (dia) {
9 case 1:
10 std::cout << "Segunda-feira\n";
11 break;
12 case 2:
13 std::cout << "Terça-feira\n";
14 break;
15 case 3:
16 std::cout << "Quarta-feira\n";
17 break;
18 case 4:
19 std::cout << "Quinta-feira\n";
20 break;
21 case 5:
22 std::cout << "Sexta-feira\n";
23 break;
24 case 6:
25 std::cout << "Sábado\n";
26 break;
27 case 7:
28 std::cout << "Domingo\n";
29 break;
30 default:
31 std::cout << "Não existe o dia " << dia << "!\n";
32 }
33}Três execuções de exemplo:
Dia da semana (1-7): 3
Quarta-feiraDia da semana (1-7): 9
Não existe o dia 9!Dia da semana (1-7): 0
Não existe o dia 0!As partes de um switch

switch (valor): o valor a examinar. Em C++ ele precisa ser de um tipo de número inteiro:int,char, umenume assim por diante.case 3:: um rótulo que marca onde começar a rodar quando o valor for 3. Os rótulos precisam ser constantes.break;: sai do switch e continua depois da chave de fechamento.default:: para onde ir quando nenhum caso bate, como oelsefinal de uma cadeia de ifs. É opcional, mas costuma ser uma boa ideia.
A grande pegadinha: esquecer o break
Um rótulo case é só um lugar para onde pular, não uma parede. Quando a execução cai num caso, ela continua descendo, atravessando os outros rótulos, até chegar a um break ou ao fim do switch. Isso se chama cair no próximo caso (fall-through):

1#include <iostream>
2
3int main() {
4 int nivel = 2;
5
6 switch (nivel) {
7 case 1:
8 std::cout << "Desbloqueado: espada\n";
9 case 2:
10 std::cout << "Desbloqueado: escudo\n";
11 case 3:
12 std::cout << "Desbloqueado: dragão\n";
13 default:
14 std::cout << "Desbloqueado: todo o resto\n";
15 }
16}Desbloqueado: escudo
Desbloqueado: dragão
Desbloqueado: todo o restoO nível 2 liberou o dragão. Ops! Ainda bem que o GCC avisa disso quando você compila com -Wextra:
1nivel.cpp: In function 'int main()':
2nivel.cpp:8:26: warning: this statement may fall through [-Wimplicit-fallthrough=]
3 8 | std::cout << "Desbloqueado: espada\n";
4 | ^~~~~~~~~~~~~~~~~~~~~~~~
5nivel.cpp:9:9: note: here
6 9 | case 2:
7 | ^~~~
8nivel.cpp:10:26: warning: this statement may fall through [-Wimplicit-fallthrough=]
9 10 | std::cout << "Desbloqueado: escudo\n";
10 | ^~~~~~~~~~~~~~~~~~~~~~~~
11nivel.cpp:11:9: note: here
12 11 | case 3:
13 | ^~~~
14nivel.cpp:12:26: warning: this statement may fall through [-Wimplicit-fallthrough=]
15 12 | std::cout << "Desbloqueado: dragão\n";
16 | ^~~~~~~~~~~~~~~~~~~~~~~~
17nivel.cpp:13:9: note: here
18 13 | default:
19 | ^~~~~~~("Esta instrução pode cair no próximo caso: aqui.")
Quando cair no próximo caso é o que você quer
Cair no próximo caso tem dois bons usos.
1. Vários valores, uma ação. Empilhe rótulos case sem nada entre eles, e todos dividem o mesmo código. Aqui C e D ganham o mesmo "Ok…":
1#include <iostream>
2
3int main() {
4 char conceitos[] = {'A', 'B', 'C', 'D', 'F', 'Z'};
5
6 for (char conceito : conceitos) {
7 std::cout << conceito << ": ";
8 switch (conceito) {
9 case 'A':
10 std::cout << "Excelente!\n";
11 break;
12 case 'B':
13 std::cout << "Ótimo!\n";
14 break;
15 case 'C':
16 case 'D':
17 std::cout << "Ok...\n";
18 break;
19 case 'F':
20 std::cout << "Hora de estudar juntos.\n";
21 break;
22 default:
23 std::cout << "Conceito inválido.\n";
24 }
25 }
26}1A: Excelente!
2B: Ótimo!
3C: Ok...
4D: Ok...
5F: Hora de estudar juntos.
6Z: Conceito inválido.Um char funciona num switch porque um caractere, no fundo, é um número pequeno: 'A' é guardado como 65.
2. Fazer isto e tudo o que vem depois. Quando cair no próximo caso for de propósito, marque com [[fallthrough]]; (C++17). Isso diz a quem lê e ao compilador "sim, era isso mesmo", e o aviso some:
1#include <iostream>
2
3int main() {
4 int segundosRestantes = 3;
5
6 std::cout << "Lançamento em: ";
7 switch (segundosRestantes) {
8 case 3:
9 std::cout << "3... ";
10 [[fallthrough]]; // de propósito: segue para o case 2
11 case 2:
12 std::cout << "2... ";
13 [[fallthrough]];
14 case 1:
15 std::cout << "1... ";
16 [[fallthrough]];
17 case 0:
18 std::cout << "Decolar!\n";
19 break;
20 }
21}Lançamento em: 3... 2... 1... Decolar!Switch e enums: uma dupla perfeita
Números soltos como case 2: não dizem muita coisa. Um enum dá nomes a um conjunto fixo de valores, e o enum class (C++11) mantém esses nomes bem agrupados. Aqui está um personagem de jogo andando numa grade:
1#include <iostream>
2
3enum class Direcao { Cima, Baixo, Esquerda, Direita };
4
5int main() {
6 int linha = 5;
7 int coluna = 5;
8 Direcao movimentos[] = {Direcao::Cima, Direcao::Cima, Direcao::Direita, Direcao::Baixo};
9
10 for (Direcao movimento : movimentos) {
11 switch (movimento) {
12 case Direcao::Cima:
13 linha--;
14 break;
15 case Direcao::Baixo:
16 linha++;
17 break;
18 case Direcao::Esquerda:
19 coluna--;
20 break;
21 case Direcao::Direita:
22 coluna++;
23 break;
24 }
25 std::cout << "Agora na linha " << linha << ", coluna " << coluna << "\n";
26 }
27}1Agora na linha 4, coluna 5
2Agora na linha 3, coluna 5
3Agora na linha 3, coluna 6
4Agora na linha 4, coluna 6case Direcao::Cima: se lê quase como português, e não tem como escrever sem querer case 7: para uma direção que não existe.
O compilador confere se você cobriu todos os casos
Tem um bônus. Quando você faz um switch num enum sem default, o compilador conhece todos os valores possíveis e avisa se você esquecer algum. Aqui falta o caso Direita:
1enum class Direcao { Cima, Baixo, Esquerda, Direita };
2
3int mudancaDeColuna(Direcao movimento) {
4 switch (movimento) {
5 case Direcao::Cima:
6 return 0;
7 case Direcao::Baixo:
8 return 0;
9 case Direcao::Esquerda:
10 return -1;
11 }
12 return 0;
13}GCC com -Wall:
1direcao.cpp: In function 'int mudancaDeColuna(Direcao)':
2direcao.cpp:4:12: warning: enumeration value 'Direita' not handled in switch [-Wswitch]
3 4 | switch (movimento) {
4 | ^("O valor 'Direita' do enum não é tratado no switch.")
Um switch dentro de um laço: máquinas de estados
Coloque um switch dentro de um laço, faça o switch sobre "em que estado eu estou?", e você montou uma máquina de estados: um dos padrões mais úteis da programação. Semáforos, máquinas de venda, personagens de jogo (parado, andando, pulando) e conexões de rede funcionam assim.

1#include <iostream>
2
3enum class Sinal { Verde, Amarelo, Vermelho };
4
5int main() {
6 Sinal sinal = Sinal::Verde;
7
8 for (int tique = 1; tique <= 6; tique++) {
9 switch (sinal) {
10 case Sinal::Verde:
11 std::cout << "Tique " << tique << ": VERDE -> siga\n";
12 sinal = Sinal::Amarelo;
13 break;
14 case Sinal::Amarelo:
15 std::cout << "Tique " << tique << ": AMARELO -> atenção\n";
16 sinal = Sinal::Vermelho;
17 break;
18 case Sinal::Vermelho:
19 std::cout << "Tique " << tique << ": VERMELHO -> pare\n";
20 sinal = Sinal::Verde;
21 break;
22 }
23 }
24}1Tique 1: VERDE -> siga
2Tique 2: AMARELO -> atenção
3Tique 3: VERMELHO -> pare
4Tique 4: VERDE -> siga
5Tique 5: AMARELO -> atenção
6Tique 6: VERMELHO -> pareO que o C++ não deixa você usar num switch

Nada de textos
Esta é a surpresa mais comum para quem vem de outras linguagens:
1#include <iostream>
2#include <string>
3
4int main() {
5 std::string saudacao = "Olá";
6 switch (saudacao) {
7 case "Olá":
8 std::cout << "Olá, tudo bem?\n";
9 break;
10 }
11}1saudacao.cpp: In function 'int main()':
2saudacao.cpp:6:13: error: switch quantity not an integer
3 6 | switch (saudacao) {
4 | ^~~~~~~~("O valor do switch não é um inteiro.") Duas boas alternativas: uma cadeia if/else (if (saudacao == "Olá") …) ou, quando houver muitos pares, uma tabela de consulta como o std::map:
1#include <iostream>
2#include <map>
3#include <string>
4
5int main() {
6 std::map<std::string, std::string> respostas = {
7 {"Bom dia", "Bom dia para você também!"},
8 {"Olá", "Olá, tudo bem?"},
9 {"Boa noite", "Boa noite, durma bem!"},
10 };
11
12 for (std::string saudacao : {"Olá", "Boa noite", "E aí"}) {
13 auto encontrada = respostas.find(saudacao);
14 if (encontrada != respostas.end()) {
15 std::cout << saudacao << " -> " << encontrada->second << "\n";
16 } else {
17 std::cout << saudacao << " -> Beleza?\n";
18 }
19 }
20}Olá -> Olá, tudo bem?
Boa noite -> Boa noite, durma bem!
E aí -> Beleza?Nada de casos repetidos
1int preco(int tamanho) {
2 switch (tamanho) {
3 case 1: return 3;
4 case 2: return 4;
5 case 2: return 5;
6 }
7 return 0;
8}1preco.cpp: In function 'int preco(int)':
2preco.cpp:5:9: error: duplicate case value
3 5 | case 2: return 5;
4 | ^~~~
5preco.cpp:4:9: note: previously used here
6 4 | case 2: return 4;
7 | ^~~~("Valor de case repetido, já usado aqui.")
Declarar uma variável dentro de um caso pede chaves
Este confunde quase todo mundo na primeira vez:
1#include <iostream>
2
3int main() {
4 int opcao = 2;
5 switch (opcao) {
6 case 1:
7 int bonus = 10;
8 std::cout << bonus << "\n";
9 break;
10 case 2:
11 std::cout << "dois\n";
12 break;
13 }
14}1bonus.cpp: In function 'int main()':
2bonus.cpp:10:14: error: jump to case label
3 10 | case 2:
4 | ^
5bonus.cpp:7:17: note: crosses initialization of 'int bonus'
6 7 | int bonus = 10;
7 | ^~~~~("Pular para o rótulo case atravessa a inicialização de 'int bonus'.") O switch inteiro é um bloco só, então bonus ainda existiria no case 2, mas pular para lá passa por cima da inicialização. A solução é dar ao caso o seu próprio bloco com chaves: case 1: { int bonus = 10; … break; }. Você vai ver isso na resposta dos dias do mês, mais abaixo.
Um switch é mais rápido que if/else?
Muita gente diz que um switch é mais rápido por causa da tabela de saltos. Testamos: a mesma decisão de 16 caminhos sobre 50 milhões de valores aleatórios, escrita dos dois jeitos, com cada caso chamando uma função diferente:

Olhando o código de máquina que o GCC gerou, a versão otimizada usou uma tabela de saltos nas duas versões: o compilador percebeu que a cadeia if/else era, na verdade, um switch disfarçado. Sem otimização, só o switch ganhou uma.
Qual usar?

A mesma ideia em outras linguagens
Muitas linguagens aceitam switch com textos. JavaScript funciona igual ao C++, com textos a mais:
1const saudacao = "Olá";
2switch (saudacao) {
3 case "Bom dia":
4 console.log("Bom dia para você também!");
5 break;
6 case "Olá":
7 console.log("Olá, tudo bem?");
8 break;
9 default:
10 console.log("Beleza?");
11}Python (a partir do 3.10) tem o match, que nunca cai no próximo caso e usa | para "qualquer um destes":
1saudacao = "Olá"
2match saudacao:
3 case "Bom dia":
4 print("Bom dia para você também!")
5 case "Olá" | "Oi":
6 print("Olá, tudo bem?")
7 case _:
8 print("Beleza?")Os dois imprimem Olá, tudo bem?.
| Linguagem | Switch com textos? | Cai no próximo caso sem break? |
|---|---|---|
| C, C++ | Não | Sim |
| Java, JavaScript, PHP | Sim | Sim |
| C# | Sim | Não: sair de um caso não vazio sem break é erro de compilação |
Python (match) | Sim | Não |
| Go | Sim | Não (a não ser que você escreva fallthrough) |
Hora de praticar
Tente fazer estes antes de espiar as respostas. Copie cada programa num arquivo, compile com g++ -std=c++20 -Wall -Wextra programa.cpp e rode.
Exercício 1: Adivinhe a saída (aquecimento). O que isto imprime?
1int numero = 2;
2switch (numero) {
3 case 1:
4 std::cout << "um ";
5 case 2:
6 std::cout << "dois ";
7 case 3:
8 std::cout << "três ";
9 break;
10 case 4:
11 std::cout << "quatro ";
12}Exercício 2: Calculadora de bolso. Dados dois números e um caractere de operação ('+', '-', '*' ou '/'), imprima o resultado. Qualquer outra coisa deve imprimir operação desconhecida.
Exercício 3: Conte as vogais. Usando um switch com casos empilhados, conte as vogais em "o comando switch e divertido".
Exercício 4: Dias do mês. Escreva int diasNoMes(int mes, int ano). Abril, junho, setembro e novembro têm 30 dias; fevereiro tem 28, ou 29 num ano bissexto; os outros têm 31.
Exercício 5: Reescreva. Transforme isto num switch. Qual versão você acha mais fácil de ler?
1if (tecla == 'w') sobe();
2else if (tecla == 's') desce();
3else if (tecla == 'a') esquerda();
4else if (tecla == 'd') direita();
5else apita();Exercício 6: Uma catraca que funciona com ficha (desafio). Uma catraca começa Travada. Uma ficha a libera; empurrar deixa uma pessoa passar e a trava de novo. Empurrar uma catraca travada não faz nada, e uma ficha numa catraca liberada é só uma gorjeta. Alimente-a com os eventos empurrar, ficha, empurrar, empurrar, ficha, ficha e imprima o que acontece.

Quiz rápido
- O que acontece se você deixar o
breakde fora no fim de um caso? - Dá para fazer
switchsobre umstd::stringem C++? O que fazer no lugar? - Por que
switch (conceito)funciona quandoconceitoé umchar? - Quando você poderia deixar o
defaultde fora de propósito? - O que o
[[fallthrough]];faz?
Respostas
Exercício 1: dois três. Ele pula para o case 2, imprime "dois ", cai no case 3, imprime "três " e encontra o break.
dois três Exercício 2:
1#include <iostream>
2
3int main() {
4 double primeiro = 12;
5 double segundo = 4;
6 char operacoes[] = {'+', '-', '*', '/', '%'};
7
8 for (char operacao : operacoes) {
9 std::cout << primeiro << " " << operacao << " " << segundo << " = ";
10 switch (operacao) {
11 case '+':
12 std::cout << primeiro + segundo << "\n";
13 break;
14 case '-':
15 std::cout << primeiro - segundo << "\n";
16 break;
17 case '*':
18 std::cout << primeiro * segundo << "\n";
19 break;
20 case '/':
21 std::cout << primeiro / segundo << "\n";
22 break;
23 default:
24 std::cout << "operação desconhecida\n";
25 }
26 }
27}112 + 4 = 16
212 - 4 = 8
312 * 4 = 48
412 / 4 = 3
512 % 4 = operação desconhecidaExercício 3: Cinco rótulos empilhados dividem um único vogais++:
1#include <iostream>
2#include <string>
3
4int main() {
5 std::string frase = "o comando switch e divertido";
6 int vogais = 0;
7 for (char letra : frase) {
8 switch (letra) {
9 case 'a':
10 case 'e':
11 case 'i':
12 case 'o':
13 case 'u':
14 vogais++;
15 break;
16 }
17 }
18 std::cout << "Vogais: " << vogais << "\n";
19}Vogais: 10Exercício 4: Casos empilhados para os meses de 30 dias, chaves em volta do bloco de fevereiro porque ele declara uma variável, e default para os meses de 31 dias:
1#include <iostream>
2
3int diasNoMes(int mes, int ano) {
4 switch (mes) {
5 case 4:
6 case 6:
7 case 9:
8 case 11:
9 return 30;
10 case 2: {
11 bool ehBissexto = (ano % 4 == 0 && ano % 100 != 0) || ano % 400 == 0;
12 return ehBissexto ? 29 : 28;
13 }
14 default:
15 return 31;
16 }
17}
18
19int main() {
20 std::cout << "Janeiro de 2025: " << diasNoMes(1, 2025) << "\n";
21 std::cout << "Abril de 2025: " << diasNoMes(4, 2025) << "\n";
22 std::cout << "Fevereiro de 2025: " << diasNoMes(2, 2025) << "\n";
23 std::cout << "Fevereiro de 2024: " << diasNoMes(2, 2024) << "\n";
24}1Janeiro de 2025: 31
2Abril de 2025: 30
3Fevereiro de 2025: 28
4Fevereiro de 2024: 29O return sai da função inteira, então esses casos não precisam de break.
Exercício 5:
1switch (tecla) {
2 case 'w': sobe(); break;
3 case 's': desce(); break;
4 case 'a': esquerda(); break;
5 case 'd': direita(); break;
6 default: apita();
7}A maioria das pessoas acha o switch mais fácil de bater o olho: as opções ficam alinhadas, e fica óbvio que todas testam a mesma tecla.
Exercício 6: Um switch sobre o estado, com um if dentro de cada caso para o evento:
1#include <iostream>
2#include <string>
3
4enum class Estado { Travada, Liberada };
5
6int main() {
7 Estado estado = Estado::Travada;
8 std::string eventos[] = {"empurrar", "ficha", "empurrar", "empurrar", "ficha", "ficha"};
9
10 for (const std::string& evento : eventos) {
11 switch (estado) {
12 case Estado::Travada:
13 if (evento == "ficha") {
14 estado = Estado::Liberada;
15 std::cout << evento << ": liberada, pode passar\n";
16 } else {
17 std::cout << evento << ": continua travada, coloque uma ficha\n";
18 }
19 break;
20 case Estado::Liberada:
21 if (evento == "empurrar") {
22 estado = Estado::Travada;
23 std::cout << evento << ": você passou, travada de novo\n";
24 } else {
25 std::cout << evento << ": já está liberada, obrigado pela gorjeta\n";
26 }
27 break;
28 }
29 }
30}1empurrar: continua travada, coloque uma ficha
2ficha: liberada, pode passar
3empurrar: você passou, travada de novo
4empurrar: continua travada, coloque uma ficha
5ficha: liberada, pode passar
6ficha: já está liberada, obrigado pela gorjetaQuiz: (1) A execução cai no código do próximo caso e continua até um break ou o fim do switch. (2) Não; use uma cadeia if/else ou uma tabela de consulta como o std::map. (3) Um char é, no fundo, um número inteiro pequeno ('A' é 65). (4) Quando o switch for sobre um enum, para o compilador avisar se algum valor não for tratado. (5) Marca que cair no próximo caso foi de propósito, para quem lê e para o compilador, que então não avisa.
Cola rápida
| Eu quero… | Escreva |
|---|---|
| Escolher uma ação pelo valor | switch (valor) { case 1: …; break; case 2: …; break; } |
| Tratar "qualquer outra coisa" | default: … |
| Dar a mesma ação a vários valores | case 'C': case 'D': …; break; |
| Cair no próximo caso de propósito | [[fallthrough]]; antes do próximo rótulo |
| Usar nomes legíveis | enum class Direcao { Cima, Baixo }; e depois case Direcao::Cima: |
| Ser avisado de casos de enum faltando | switch sobre o enum sem default, compilando com -Wall |
| Declarar uma variável dentro de um caso | envolva com chaves: case 1: { int bonus = 10; … break; } |
| Escolher por texto | if (texto == "Olá") … else if … ou um std::map |
| Montar uma máquina de estados | um switch (estado) dentro de um laço que atualiza o estado |
Resumindo
O comando switch é um jeito limpo de dizer "olhe este valor e escolha o caminho que bate":
- Um switch pula para o
caseque bate, e odefaultpega todo o resto. - O
breakimporta: sem ele, a execução cai nos casos de baixo. O-Wextraavisa, e o[[fallthrough]]marca as vezes em que é de propósito. - Rótulos empilhados dão a mesma ação a vários valores.
- Enums e switches andam juntos: nomes legíveis, e um aviso quando algum valor não é tratado.
- Um switch num laço vira uma máquina de estados, o coração de jogos, aparelhos e protocolos.
- Switches em C++ só funcionam com números inteiros,
chars e enums. Para textos, use if/else ou umstd::map. - Na velocidade, empate: com a otimização ligada, o GCC montou a mesma tabela de saltos para uma cadeia if/else. Escolha o que se lê melhor.
Continue com O Comando If, O Laço For e Os Laços While e Do-While.
Leia a seguir

O Que É a Linguagem de Programação Rust? Um Guia Simples da Linguagem Rápida Que Não Deixa Você Travar
Um guia simples e sem jargões sobre o Rust, a linguagem tão rápida quanto o C que impede famílias inteiras de erros de memória antes de o programa rodar. Entenda a ideia de posse, por que gigantes da tecnologia o adotam e onde ele é usado.

O Que É a Linguagem de Programação Go? Um Guia Simples da Linguagem da Nuvem
Um guia simples e sem jargões sobre o Go, a linguagem simples e rápida que o Google criou para a nuvem. Entenda o que são goroutines, por que um programa Go é um arquivo só e como o Go passou a mover o Docker, o Kubernetes e boa parte da internet.

O Que É a Linguagem de Programação Ruby? Um Guia Simples da Linguagem Feita para a Felicidade
Um guia simples e sem jargões sobre o Ruby, a linguagem de programação feita para deixar os programadores felizes. Entenda por que o código Ruby parece inglês, como o Ruby on Rails move sites como GitHub e Shopify, e onde o Ruby brilha.
Comentários
Seja gentil e específico. Comentários com links de contas novas aparecem depois da análise de um moderador.