A instrução switch em C
LidoEsta aula explora a instrução switch em C, cobrindo sua sintaxe, o papel do break e do fall-through, o uso do default e as principais limitações. Através de exemplos práticos e explicações detalhadas, você aprenderá a usar switch para tomadas de decisão multi-caminho de forma eficiente e evitar armadilhas comuns.
A instrução switch é uma estrutura de controle de fluxo em C que permite selecionar um entre vários blocos de código com base no valor de uma expressão inteira. Ela é uma alternativa mais legível e eficiente a uma cadeia de if-else if quando você precisa comparar uma variável com vários valores constantes. Nesta aula, vamos mergulhar na sintaxe, no comportamento do break, no fall-through, no uso do default e nas limitações dessa construção.
Ao dominar o switch, você será capaz de escrever código mais claro e organizado para menus, máquinas de estado e despacho de comandos. Além disso, entenderá as nuances que podem causar bugs sutis, como o fall-through acidental.
Sintaxe
A sintaxe básica do switch é a seguinte:
switch (expressão) {
case constante1:
// bloco de código para constante1
break;
case constante2:
// bloco de código para constante2
break;
// ... mais casos
default:
// bloco executado se nenhum caso corresponder
}
A expressão avaliada deve ser de tipo inteiro (int, char, enum, etc.). Os valores nos rótulos case devem ser constantes de tempo de compilação, ou seja, valores conhecidos durante a compilação. Cada case pode conter uma ou mais instruções, e o bloco termina quando um break é encontrado ou quando o final da instrução switch é atingido (o que causaria fall-through).
Vejamos um exemplo simples:
#include <stdio.h>
int main() {
int dia = 3;
switch (dia) {
case 1:
printf("Domingo\n");
break;
case 2:
printf("Segunda-feira\n");
break;
case 3:
printf("Terça-feira\n");
break;
default:
printf("Dia inválido\n");
}
return 0;
}
Nesse exemplo, a variável dia é comparada com os valores 1, 2 e 3. Como dia é 3, o programa imprime "Terça-feira".
break e fall-through
O break é uma instrução que interrompe a execução do switch e pula para a próxima instrução após o bloco. Sem o break, ocorre o chamado fall-through: a execução continua nos casos seguintes, mesmo que não correspondam ao valor avaliado. Isso pode ser útil em algumas situações, mas muitas vezes é um erro.
Exemplo de fall-through intencional:
int dia = 3;
switch (dia) {
case 1:
case 2:
case 3:
printf("É um dia útil (segunda a terça)\n");
break;
case 4:
printf("Quarta-feira\n");
break;
default:
printf("Fim de semana ou inválido\n");
}
Aqui, os casos 1, 2 e 3 compartilham o mesmo código, porque não há break entre eles. Isso é uma técnica comum para agrupar valores.
Porém, o fall-through acidental é uma fonte comum de bugs. Considere:
int x = 2;
switch (x) {
case 1:
printf("Um\n");
case 2:
printf("Dois\n");
case 3:
printf("Três\n");
}
Se x for 2, a saída será "Dois" e "Três" porque não há break após o caso 2. Para evitar isso, sempre coloque break a menos que você queira o fall-through.
default
A cláusula default é executada quando nenhum dos case corresponde ao valor da expressão. Ela é opcional, mas recomendada para tratar valores inesperados. Pode aparecer em qualquer lugar dentro do switch, mas geralmente é colocada no final.
Exemplo com default:
char opcao = 'B';
switch (opcao) {
case 'A':
printf("Adicionar\n");
break;
case 'B':
printf("Buscar\n");
break;
case 'C':
printf("Cancelar\n");
break;
default:
printf("Opção inválida\n");
}
Se opcao for 'B', imprime "Buscar". Se for 'X', imprime "Opção inválida". O default também pode ser usado para capturar erros e fornecer feedback ao usuário.
É importante notar que o default não precisa ser o último, mas se não houver break no default e ele não for o último, pode causar fall-through também.
Limitações
O switch em C tem várias limitações em comparação com outras linguagens:
- Apenas tipos inteiros: A expressão deve ser de tipo inteiro (int, char, enum). Não é possível comparar strings, floats ou ponteiros diretamente.
- Constantes de tempo de compilação: Os valores nos rótulos
casedevem ser constantes literais ou expressões constantes (por exemplo, macros). Não podem ser variáveis ou expressões que dependam de valores em tempo de execução. - Sem intervalos: Diferente de algumas linguagens, C não suporta intervalos como
case 1 ... 10. Você precisa listar cada valor ou usar fall-through. - Não há verificação de escopo implícita: Se você declarar variáveis dentro de um
case, elas podem causar problemas de escopo. É recomendável usar chaves{}para criar um bloco, mas as variáveis ainda são visíveis em todo oswitchse não forem inicializadas corretamente. - Dificuldade com lógica complexa: Para condições mais complexas (como intervalos ou comparações),
if-elseé mais adequado.
Apesar dessas limitações, o switch é muito útil para despachar comandos e menus, onde a clareza e a eficiência são importantes.
Boas práticas
- Sempre use
breakao final de cadacase, a menos que haja fall-through intencional. - Inclua
defaultpara tratar valores inesperados. - Use chaves
{}para isolar variáveis locais em cadacase, evitando conflitos de declaração. - Evite
switchsobre expressões com muitos casos (mais de 20) – considere uma tabela de ponteiros para função. - Mantenha os casos em ordem numérica ou alfabética para melhor legibilidade.
Exercícios
- Escreva um programa que leia um número de 1 a 7 e imprima o dia da semana correspondente, usando
switch. Incluadefaultpara números fora do intervalo. - Explique o que acontece se você omitir o
breakem umcase. Dê um exemplo de código que demonstre o fall-through e a saída gerada. - Usando o fall-through intencional, escreva um programa que classifique uma nota (0-10) como "Reprovado" para notas < 5, "Recuperação" para 5-6, e "Aprovado" para 7-10. Use
switchcom agrupamento de casos. - Escreva um programa que use
switchpara operações aritméticas simples: leia dois números e um operador (+, -, *, /) e imprima o resultado. Usedefaultpara operador inválido. - Explique as limitações do
switchem C. Cite pelo menos três e dê um exemplo de situação em queif-elseseria mais adequado.
#include <stdio.h>
int main() {
int num;
printf("Digite um número de 1 a 7: ");
scanf("%d", &num);
switch (num) {
case 1: printf("Domingo\n"); break;
case 2: printf("Segunda-feira\n"); break;
case 3: printf("Terça-feira\n"); break;
case 4: printf("Quarta-feira\n"); break;
case 5: printf("Quinta-feira\n"); break;
case 6: printf("Sexta-feira\n"); break;
case 7: printf("Sábado\n"); break;
default: printf("Número inválido\n");
}
return 0;
}
break for omitido, a execução continua no próximo case, mesmo que o valor não corresponda. Isso é chamado de fall-through. Exemplo: int x = 2;
switch (x) {
case 1:
printf("Um\n");
case 2:
printf("Dois\n");
case 3:
printf("Três\n");
} A saída será "Dois" e "Três" porque não há break após o caso 2.#include <stdio.h>
int main() {
int nota;
printf("Digite a nota (0-10): ");
scanf("%d", ¬a);
switch (nota) {
case 0:
case 1:
case 2:
case 3:
case 4:
printf("Reprovado\n");
break;
case 5:
case 6:
printf("Recuperação\n");
break;
case 7:
case 8:
case 9:
case 10:
printf("Aprovado\n");
break;
default:
printf("Nota inválida\n");
}
return 0;
}
#include <stdio.h>
int main() {
double a, b, resultado;
char op;
printf("Digite dois números: ");
scanf("%lf %lf", &a, &b);
printf("Digite o operador (+, -, *, /): ");
scanf(" %c", &op);
switch (op) {
case '+': resultado = a + b; break;
case '-': resultado = a - b; break;
case '*': resultado = a * b; break;
case '/':
if (b == 0) {
printf("Erro: divisão por zero\n");
return 1;
}
resultado = a / b; break;
default:
printf("Operador inválido\n");
return 1;
}
printf("Resultado: %.2f\n", resultado);
return 0;
}
x está em um intervalo (ex.: 10 < x < 20), if-else é mais adequado: if (x > 10 && x < 20) {
printf("Entre 10 e 20\n");
} else {
printf("Fora do intervalo\n");
}