Aula 08 – Estrutura if e if-else

Tomando decisões em C — condições simples, duplas e fluxo de controle

O que são Estruturas de Decisão?

Programas raramente executam sempre o mesmo caminho. A maioria das situações reais exige que o código tome decisões: verificar se uma senha está correta, determinar se um número é positivo ou negativo, ou escolher qual mensagem exibir ao usuário. Para isso existem as estruturas de decisão.

Uma estrutura de decisão avalia uma condição (expressão que resulta em verdadeiro ou falso) e direciona o fluxo de execução para blocos de código diferentes dependendo do resultado. Em C, a condição é qualquer expressão cujo resultado seja um inteiro: 0 é falso e qualquer valor diferente de zero é verdadeiro.
Estruturas de decisão em C — visão geral: Nesta aula focaremos nas duas primeiras formas: if e if-else.

Estrutura if — Decisão Simples

A estrutura if executa um bloco de código somente se a condição for verdadeira. Se a condição for falsa, o bloco é simplesmente pulado.

if (condição) {
    // bloco executado apenas se condição for verdadeira
}
condição
↓ verdadeiro
bloco if
↓
↓ falso
(pula)
↓
continua o programa
#include <stdio.h>

int main() {
    int isStudent = 1;   // 1 = verdadeiro
    int temperatura = 38;

    // if simples: só executa se isStudent for não-zero
    if (isStudent) {
        printf("Você é estudante.\n");
    }

    // if com operador relacional
    if (temperatura > 37.5) {
        printf("Atenção: temperatura elevada (%.1f°C).\n", (float)temperatura);
    }

    printf("Fim do programa.\n");  // sempre executado
    return 0;
}

Você é estudante.

Atenção: temperatura elevada (38.0°C).

Fim do programa.

if sem chaves — cuidado!

Quando o bloco do if tem apenas uma instrução, as chaves são opcionais em C. Porém, omiti-las é uma fonte frequente de bugs:

// Válido — mas arriscado
if (temperatura > 37.5)
    printf("Febre!\n");   // única instrução: pertence ao if
printf("Consulte um médico.\n"); // SEMPRE executa — fora do if!

// Seguro — sempre use chaves
if (temperatura > 37.5) {
    printf("Febre!\n");
    printf("Consulte um médico.\n");  // agora pertence ao bloco do if
}
Boa prática: Sempre use chaves { } em blocos if, mesmo quando há apenas uma instrução. Isso evita o bug clássico de adicionar uma segunda linha acreditando que ela também faz parte do if — quando na realidade está fora dele.

Estrutura if-else — Decisão Dupla

A estrutura if-else permite escolher entre dois caminhos: um executado quando a condição é verdadeira e outro quando é falsa. Exatamente um dos dois blocos sempre será executado.

if (condição) {
    // bloco executado se condição for VERDADEIRA
} else {
    // bloco executado se condição for FALSA
}
condição
↙ verdadeiro        falso ↘
bloco if
bloco else
↓                   ↓
continua o programa
#include <stdio.h>

int main() {
    int age = 20;

    // if-else: exatamente um dos blocos será executado
    if (age < 18) {
        printf("Menor de idade.\n");
    } else {
        printf("Maior de idade.\n");   // este executa (20 >= 18)
    }

    // Verificando par ou ímpar
    int numero = 7;
    if (numero % 2 == 0) {
        printf("%d é par.\n", numero);
    } else {
        printf("%d é ímpar.\n", numero);  // este executa
    }

    return 0;
}

Maior de idade.

7 é ímpar.

if-else Aninhado

Estruturas if-else podem ser colocadas dentro de outras — chamamos isso de aninhamento. Isso permite verificar condições progressivamente mais específicas.

#include <stdio.h>

int main() {
    int nota = 75;
    int faltas = 5;

    if (nota >= 60) {
        // nota suficiente — mas e as faltas?
        if (faltas <= 25) {
            printf("Aprovado: nota %.0d e frequência suficiente.\n", nota);
        } else {
            printf("Reprovado por falta, apesar da nota %d.\n", nota);
        }
    } else {
        printf("Reprovado por nota insuficiente: %d.\n", nota);
    }

    return 0;
}

Aprovado: nota 75 e frequência suficiente.

DICA — o problema do "else solto" (dangling else): Em C, um else sempre se associa ao if mais próximo acima dele. Se as chaves forem omitidas em aninhamentos, o compilador pode interpretar o código de forma diferente da intenção do programador. Use sempre chaves para deixar o agrupamento explícito.
// Ambíguo sem chaves — a qual if pertence o else?
if (a > 0)
    if (b > 0)
        printf("ambos positivos\n");
else                   // associa ao "if (b > 0)", não ao "if (a > 0)"!
    printf("b não é positivo\n");

// Claro com chaves
if (a > 0) {
    if (b > 0) {
        printf("ambos positivos\n");
    }
} else {               // agora claramente pertence ao "if (a > 0)"
    printf("a não é positivo\n");
}

Condições Compostas no if

A condição de um if pode combinar múltiplos operadores relacionais e lógicos para expressar critérios mais complexos:

#include <stdio.h>

int main() {
    int idade = 22;
    float salario = 3500.0;
    int temCPF = 1;

    // Aprovação de crédito: múltiplas condições com && e ||
    if (idade >= 18 && salario >= 2000.0 && temCPF) {
        printf("Crédito aprovado.\n");
    } else {
        printf("Crédito negado.\n");
    }

    // Verificação de faixa de temperatura
    float temp = 36.8;
    if (temp >= 36.0 && temp <= 37.5) {
        printf("Temperatura normal: %.1f°C\n", temp);
    } else {
        printf("Temperatura fora do normal: %.1f°C\n", temp);
    }

    // Acesso por categoria
    int vip = 0, convidado = 1;
    if (vip || convidado) {
        printf("Acesso liberado ao evento.\n");
    }

    return 0;
}

Crédito aprovado.

Temperatura normal: 36.8°C

Acesso liberado ao evento.

Exemplo do Material de Referência

O trecho abaixo, extraído diretamente da seção 5 do livro de referência do curso, demonstra o if simples e o if-else aplicados a um cenário de controle de acesso:

#include <stdio.h>

int main() {
    int age = 25;
    int isStudent = 1;

    // if simples: executa apenas se isStudent for verdadeiro
    if (isStudent) {
        printf("You are a student.\n");
    }

    // if-else: escolhe entre dois caminhos
    if (age < 18) {
        printf("Underage.\n");
    } else {
        printf("Of legal age.\n");
    }

    return 0;
}

You are a student.

Of legal age.

Observe: if (isStudent) é equivalente a if (isStudent != 0). Como isStudent = 1 (não-zero), a condição é verdadeira. Essa forma concisa é idiomática em C e amplamente usada com variáveis que funcionam como flags (ligado/desligado).

Exemplo Prático: Classificação de Energia Molecular

Aplicando if-else a um contexto do curso — análise do sinal de energia calculada:

#include <stdio.h>

int main() {
    double energia = -74.96;   // energia em Hartree (valor típico do H₂O)

    printf("Energia calculada: %.4f Hartree\n", energia);

    if (energia < 0) {
        printf("Sistema estável: energia negativa indica estado ligado.\n");
    } else {
        printf("Sistema instável: energia positiva indica estado não ligado.\n");
    }

    // Verificando convergência do cálculo
    double delta = 0.000003;   // diferença entre iterações
    double tolerancia = 1e-5;  // critério de convergência

    if (delta <= tolerancia) {
        printf("Cálculo convergido (delta = %.2e).\n", delta);
    } else {
        printf("Cálculo ainda não convergiu (delta = %.2e).\n", delta);
    }

    return 0;
}

Energia calculada: -74.9600 Hartree

Sistema estável: energia negativa indica estado ligado.

Cálculo convergido (delta = 3.00e-06).

if e if-else em C versus Java

A sintaxe de if e if-else é praticamente idêntica nas duas linguagens. As diferenças estão no sistema de tipos e no que é aceito como condição:

Aspecto C Java
Sintaxe do if if (condição) { } if (condição) { } (idêntica)
Sintaxe do if-else if (...) { } else { } if (...) { } else { } (idêntica)
Tipo da condição Qualquer inteiro — 0 é falso, não-zero é verdadeiro Deve ser boolean — true ou false
if (x) com inteiro Válido — compila sem erro Inválido — erro de compilação
if (x = 5) (atribuição) Compila sem erro — bug silencioso Erro de compilação (tipo incompatível)
Chaves opcionais (bloco único) Sim — mas não recomendado Sim — mas não recomendado
Dangling else Ocorre sem chaves — else ao if mais próximo Mesma regra — idêntico ao C

Código equivalente nas duas linguagens

C Java
int age = 20;
int isStudent = 1;

if (isStudent) {
    printf("Estudante.\n");
}

if (age < 18) {
    printf("Menor.\n");
} else {
    printf("Maior.\n");
}
int age = 20;
boolean isStudent = true;

if (isStudent) {
    System.out.println("Estudante.");
}

if (age < 18) {
    System.out.println("Menor.");
} else {
    System.out.println("Maior.");
}

Exercícios — Aula 08

Teste seus conhecimentos sobre estruturas if e if-else em C:

1. Qual será a saída do código abaixo?

int x = 0;
if (x)
    printf("verdadeiro\n");
printf("sempre\n");

2. Analise o código. Qual será a saída?

int a = 10, b = 20;
if (a > b) {
    printf("A\n");
} else {
    printf("B\n");
}
printf("C\n");

3. Por que é recomendado usar chaves { } mesmo quando o bloco do if tem apenas uma instrução?

4. O código abaixo tem um bug clássico. O que ele imprime quando a = -3?

int a = -3;
if (a > 0)
    printf("positivo\n");
    printf("nao negativo\n");

5. Qual das condições abaixo é válida diretamente em um if em C, mas inválida em Java?

6. Analise o código. A qual if o else se associa?

if (a > 0)
    if (b > 0)
        printf("X\n");
else
    printf("Y\n");

7. Qual será a saída do código abaixo?

int nota = 55;
int faltas = 30;

if (nota >= 60) {
    if (faltas <= 25) {
        printf("Aprovado\n");
    } else {
        printf("Reprovado por falta\n");
    }
} else {
    printf("Reprovado por nota\n");
}

8. Qual é a diferença fundamental entre o tipo da condição em um if em C e em Java?