Condicionais: if, else e switch

1. Introdução às Estruturas Condicionais

As estruturas condicionais são o coração da tomada de decisão em qualquer programa. Em Linguagem C, elas permitem que o fluxo de execução do código seja desviado com base em condições avaliadas em tempo de execução. Sem condicionais, todo programa seria uma sequência linear de instruções, incapaz de reagir a diferentes entradas ou estados.

O mecanismo fundamental por trás das condicionais em C é a avaliação de expressões como verdadeiras ou falsas. Diferente de outras linguagens, C não possui um tipo booleano nativo (até C99, com _Bool). Em C, qualquer valor diferente de zero é considerado verdadeiro, e o valor zero é considerado falso. Essa característica é essencial para entender o comportamento de if, else e switch.

2. O Comando if

A sintaxe básica do comando if é:

if (expressão) {
    // bloco de código executado se expressão for verdadeira
}

A expressão entre parênteses é avaliada. Se o resultado for diferente de zero, o bloco de código é executado. Caso contrário, o fluxo segue para a próxima instrução após o if.

Exemplo prático: verificar se um número é positivo.

#include <stdio.h>

int main() {
    int numero = 10;

    if (numero > 0) {
        printf("O número %d é positivo.\n", numero);
    }

    return 0;
}

O uso de chaves {} é obrigatório quando o bloco contém mais de uma instrução. Para uma única instrução, as chaves são opcionais, mas é uma boa prática sempre utilizá-las para evitar erros de interpretação e melhorar a legibilidade. A indentação consistente também é crucial para entender a estrutura do código.

3. O Comando else

O else complementa o if, definindo um bloco de código que será executado quando a condição do if for falsa.

if (expressão) {
    // bloco se verdadeiro
} else {
    // bloco se falso
}

Exemplo: determinar se um número é par ou ímpar.

#include <stdio.h>

int main() {
    int numero = 7;

    if (numero % 2 == 0) {
        printf("%d é par.\n", numero);
    } else {
        printf("%d é ímpar.\n", numero);
    }

    return 0;
}

Um cuidado importante com o else é evitar o "else solto" — ou seja, um else que não está claramente associado a um if específico. Em estruturas aninhadas, o else sempre se liga ao if mais próximo que ainda não possui um else correspondente. O uso de chaves elimina essa ambiguidade.

4. Encadeamento com else if

Para testar múltiplas condições em sequência, utilizamos a estrutura if-else if-else:

if (condicao1) {
    // bloco 1
} else if (condicao2) {
    // bloco 2
} else if (condicao3) {
    // bloco 3
} else {
    // bloco padrão
}

Exemplo: classificar uma nota de 0 a 100 em conceitos A, B, C, D ou F.

#include <stdio.h>

int main() {
    int nota = 85;

    if (nota >= 90) {
        printf("Conceito A\n");
    } else if (nota >= 80) {
        printf("Conceito B\n");
    } else if (nota >= 70) {
        printf("Conceito C\n");
    } else if (nota >= 60) {
        printf("Conceito D\n");
    } else {
        printf("Conceito F\n");
    }

    return 0;
}

Essa abordagem é mais eficiente e lógica do que usar múltiplos if independentes, pois assim que uma condição é satisfeita, as demais são ignoradas. Com if independentes, todas as condições seriam avaliadas desnecessariamente.

5. Operadores Relacionais e Lógicos em Condicionais

As condições dentro de if utilizam operadores relacionais e lógicos.

Operadores relacionais:

Operador Significado
== igual a
!= diferente de
< menor que
> maior que
<= menor ou igual a
>= maior ou igual a

Operadores lógicos:

Operador Significado
&& E lógico
|| OU lógico
! NÃO lógico

Exemplo: validar se um número está no intervalo de 0 a 100.

#include <stdio.h>

int main() {
    int valor = 50;

    if (valor >= 0 && valor <= 100) {
        printf("%d está no intervalo [0, 100].\n", valor);
    } else {
        printf("%d está fora do intervalo.\n", valor);
    }

    return 0;
}

A combinação de operadores permite criar condições complexas de forma clara e concisa.

6. O Comando switch

O switch é uma estrutura condicional alternativa, ideal para testar uma expressão contra múltiplos valores discretos.

switch (expressão) {
    case valor1:
        // código para valor1
        break;
    case valor2:
        // código para valor2
        break;
    default:
        // código padrão (opcional)
}

Exemplo: menu de opções.

#include <stdio.h>

int main() {
    int opcao = 2;

    switch (opcao) {
        case 1:
            printf("Opção 1 selecionada: Cadastro\n");
            break;
        case 2:
            printf("Opção 2 selecionada: Consulta\n");
            break;
        case 3:
            printf("Opção 3 selecionada: Relatório\n");
            break;
        default:
            printf("Opção inválida\n");
    }

    return 0;
}

O comando break é fundamental: ele interrompe a execução do switch e sai da estrutura. Sem o break, ocorre o fenômeno de fall-through: a execução continua para o próximo case, independentemente do valor. Isso pode ser útil em alguns casos (como agrupar múltiplos valores), mas geralmente é fonte de bugs.

7. Diferenças entre if-else e switch

A escolha entre if-else e switch depende do contexto:

  • Use switch quando: a condição for baseada em uma única expressão que assume valores discretos (inteiros, caracteres ou enumerações). O código fica mais legível e organizado.
  • Use if-else quando: as condições envolverem intervalos numéricos, expressões complexas, operadores lógicos ou comparações com diferentes variáveis.

Limitações do switch em C:
- A expressão deve ser de tipo inteiro (int, char, enum) — não funciona com floats, strings ou ponteiros.
- Os valores dos case devem ser constantes em tempo de compilação.
- Não é possível testar intervalos diretamente (ex: case 1..5 não é válido).

Em termos de desempenho, o compilador pode otimizar um switch com muitos casos para uma tabela de desvio (jump table), tornando-o potencialmente mais rápido que uma cadeia de if-else. Contudo, para a maioria das aplicações, a diferença é irrelevante; a legibilidade deve ser o critério principal.

8. Boas Práticas e Armadilhas Comuns

Erro clássico: = no lugar de ==

// ERRADO: atribuição, não comparação
if (x = 5) {
    printf("x é 5");
}

Esse código compila sem erros, mas atribui 5 a x e sempre entra no if, pois o resultado da atribuição (5) é diferente de zero. Sempre use == para comparação.

Uso de constantes simbólicas:

Em vez de números mágicos, defina constantes com #define ou enum para tornar o código mais legível e fácil de manter.

#define OPC_CADASTRO 1
#define OPC_CONSULTA 2

switch (opcao) {
    case OPC_CADASTRO:
        // ...
        break;
    case OPC_CONSULTA:
        // ...
        break;
}

Evite if aninhados profundos: mais de três níveis de aninhamento tornam o código difícil de ler. Considere refatorar com funções auxiliares ou reestruturar a lógica.

Sempre inclua o default no switch: mesmo que você acredite que todos os casos estão cobertos, o default captura valores inesperados e evita comportamentos silenciosos.

Dominar as estruturas condicionais é essencial para escrever código C claro, correto e eficiente. Pratique com exemplos variados e sempre questione qual estrutura melhor se adequa ao problema que você está resolvendo.

Referências