C++ if e else

Até aqui, seus programas executavam todas as linhas, de cima para baixo, sempre do mesmo jeito. Mas a vida é cheia de decisões: se a nota for 7 ou mais, a aluna passou; senão, vai para a recuperação. Nesta aula você vai ensinar o programa a decidir com if ("se") e else ("senão"), entender por que as chaves { } importam tanto e conhecer três armadilhas clássicas que o compilador ajuda a pegar.

Você vai aprender
  • Como escrever um if: a condição entre parênteses e o bloco entre chaves.
  • Como dar um caminho alternativo com else.
  • O que pode ser uma condição (comparações, bool, até números).
  • O bug do if sem chaves com duas linhas, e o aviso que o g++ dá.
  • Por que if (x = 5) está errado, e o ponto e vírgula que "desliga" o if.
  • O if com inicializador: if (int n = …; n > 0) C++17.

Todos os programas desta aula foram compilados com o g++ 15.2 na máquina fictícia da Ana (usuária ana, computador notebook), com g++ -std=c++23 -Wall -Wextra arquivo.cpp -o programa. Os avisos que aparecem aqui só são mostrados por causa do -Wall -Wextra (aula Avisos): nunca compile sem eles.


A ideia: a bifurcação na estrada

Imagine a Ana dirigindo até chegar a uma bifurcação com uma placa: "Se estiver chovendo, pegue a estrada coberta. Senão, pegue a estrada da praia". Ela olha para o céu (a condição), e a resposta só pode ser sim ou não. Conforme a resposta, ela segue por um caminho ou pelo outro. Depois, os dois caminhos voltam a se encontrar e a viagem continua.

Na estradaNo C++
"Se estiver chovendo"if (chovendo)
O caminho do "sim"o bloco { … } logo depois do if
"Senão"else
O caminho do "não"o bloco { … } logo depois do else
Os caminhos se juntama primeira linha depois do if/else

1. O if sozinho

#include <iostream>

int main() {
    double nota = 8.5;

    if (nota >= 7) {
        std::cout << "Aprovada!\n";
    }
    std::cout << "Fim do boletim.\n";
}
if
"Se". Palavra reservada do C++: não pode ser nome de variável.
(nota >= 7)
A condição, sempre entre parênteses. Ela é uma pergunta de sim ou não: "a nota é maior ou igual a 7?". A resposta é um bool: true (verdadeiro) ou false (falso) (aulas Booleanos e Operadores de Comparação).
{ … }
O bloco: as linhas que só rodam se a condição for verdadeira. Pode ter quantas linhas você quiser.
Sem ; depois do )
A linha do if não termina com ponto e vírgula. As linhas dentro do bloco, sim. (O que acontece se você puser um ; ali está na seção 5.)
Os 4 espaços
O recuo (a indentação) mostra a quem lê o que está dentro do bloco. O compilador não liga para os espaços, só para as chaves; mas sem recuo o código fica ilegível.
$ g++ -std=c++23 -Wall -Wextra nota.cpp -o nota
$ ./nota
Aprovada!
Fim do boletim.          « esta linha está fora do if: roda sempre

Troque a nota para 5.5, compile e rode de novo: só aparece Fim do boletim.. O bloco foi pulado.

As condições mais comuns

CondiçãoLê-seExemplo
a == ba é igual a b (dois sinais de igual!)if (senha == 1234)
a != ba é diferente de bif (resposta != 'S')
a < b, a > bmenor, maiorif (idade < 18)
a <= b, a >= bmenor ou igual, maior ou igualif (nota >= 7)
c1 && c2c1 e c2if (nota >= 7 && faltas < 10)
c1 || c2c1 ou c2if (dia == 6 || dia == 7)
!cnão cif (!pagou)

Os operadores &&, || e ! têm aula própria: Operadores Lógicos.


2. O caminho alternativo: else

O else ("senão") vem logo depois do bloco do if e diz o que fazer quando a condição é falsa. Um dos dois blocos sempre roda, nunca os dois:

#include <iostream>

int main() {
    double nota = 5.5;

    if (nota >= 7) {
        std::cout << "Aprovada!\n";
        std::cout << "Parabéns!\n";
    } else {
        std::cout << "Recuperação.\n";
        std::cout << "A prova é dia 10.\n";
    }
    std::cout << "Fim do boletim.\n";
}
$ ./nota2
Recuperação.             « 5.5 >= 7 é falso: rodou o bloco do else
A prova é dia 10.
Fim do boletim.
  1. O programa calcula a condição nota >= 7 → 5.5 >= 7 → false.
  2. Como é falsa, pula o bloco do if inteiro (as duas linhas).
  3. Roda o bloco do else (as duas linhas).
  4. Segue para a linha depois do else: Fim do boletim..

O else não tem condição: ele é simplesmente "todos os outros casos". Se você precisa de mais de dois caminhos (A, B ou C), use else if, a próxima aula.

Missão: com a nota 5.5, este programa não mostra nada sobre a aluna. Acrescente um else que mostre Recuperação quando a nota for menor que 7. Depois, teste com outras notas.

#include <iostream>

int main() {
    double nota = 5.5;

    if (nota >= 7) {
        std::cout << "Aprovada\n";
    }
}
#include <iostream>

int main() {
    double nota = 5.5;

    if (nota >= 7) {
        std::cout << "Aprovada\n";
    } else {
        std::cout << "Recuperação\n";
    }
}

Decidir com o que o usuário digitou

A decisão fica mais interessante quando o valor vem do teclado, com std::cin (aula Entrada com cin):

#include <iostream>

int main() {
    int idade = 0;
    std::cout << "Sua idade: ";
    std::cin >> idade;

    if (idade >= 18) {
        std::cout << "Pode tirar a carteira de motorista.\n";
    } else {
        std::cout << "Faltam " << 18 - idade << " anos.\n";
    }
}
$ ./cin
Sua idade: 15            « a Ana digitou 15 e Enter
Faltam 3 anos.
$ ./cin
Sua idade: 30
Pode tirar a carteira de motorista.

3. O que pode ser uma condição

A condição precisa resultar em true ou false. Além das comparações, valem:

  • Uma variável bool: bool pagou = true; if (pagou) { … }. Não precisa escrever if (pagou == true).
  • Um número: o C++ converte 0 em false e qualquer outro número em true. Herança da linguagem C.
#include <iostream>

int main() {
    int estoque = 0;
    if (estoque) {
        std::cout << "Tem no estoque\n";
    } else {
        std::cout << "Esgotado\n";
    }
}
$ ./numero
Esgotado                 « 0 conta como false

Funciona, mas if (estoque > 0) diz a mesma coisa de um jeito que qualquer pessoa entende. Prefira a comparação explícita com números; deixe o if (x) para variáveis bool.


4. Chaves: com e sem { }

Quando o bloco tem uma linha só, o C++ deixa você omitir as chaves:

if (nota >= 7)
    std::cout << "Aprovada!\n";
else
    std::cout << "Recuperação.\n";

Sem chaves, o if controla só a próxima instrução, até o primeiro ;. O problema aparece quando alguém, depois, acrescenta uma segunda linha achando que ela também fica "dentro":

#include <iostream>

int main() {
    double nota = 5.5;

    if (nota >= 7)
        std::cout << "Aprovada!\n";
        std::cout << "Parabéns!\n";

    std::cout << "Fim do boletim.\n";
}
$ g++ -std=c++23 -Wall -Wextra semchaves.cpp -o semchaves
semchaves.cpp: In function ‘int main()’:
semchaves.cpp:6:5: warning: this ‘if’ clause does not guard... [-Wmisleading-indentation]
    6 |     if (nota >= 7)
      |     ^~
semchaves.cpp:8:9: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘if’
    8 |         std::cout << "Parabéns!\n";
      |         ^~~
$ ./semchaves
Parabéns!                « nota 5.5, e mesmo assim deu parabéns!
Fim do boletim.

A linha 8 está recuada como se fosse do if, mas para o compilador ela está fora: roda sempre. O aviso diz exatamente isso: "esta cláusula if não protege… esta instrução, mas a última está recuada de um jeito enganoso, como se fosse protegida pelo if". Misleading indentation = "indentação enganosa".

Regra deste guia: chaves sempre

Use { } mesmo com uma linha só. Custa dois caracteres e elimina esse bug. Em 2014, um erro desse tipo (uma linha duplicada depois de um if sem chaves) desligou uma verificação de segurança do sistema da Apple: o famoso bug "goto fail". Sem o -Wall, o g++ nem teria avisado.

Experimente: rode e veja o aviso e o "Parabéns!" indevido. Depois coloque chaves em volta das duas linhas do if e rode de novo.

#include <iostream>

int main() {
    double nota = 5.5;

    if (nota >= 7)
        std::cout << "Aprovada!\n";
        std::cout << "Parabéns!\n";

    std::cout << "Fim do boletim.\n";
}

Onde pôr as chaves

Há dois estilos populares, e os dois são corretos. Escolha um e use sempre o mesmo:

Chave na mesma linha (usado neste guia)Chave na linha de baixo
if (nota >= 7) {
    std::cout << "Sim\n";
} else {
    std::cout << "Não\n";
}
if (nota >= 7)
{
    std::cout << "Sim\n";
}
else
{
    std::cout << "Não\n";
}

5. Duas armadilhas: = no lugar de ==, e o ; depois do if

if (x = 5): atribuição em vez de comparação

Um = é atribuição ("x recebe 5"); dois, ==, é comparação ("x é igual a 5?"). Trocar um pelo outro dentro do if compila, mas faz outra coisa:

#include <iostream>

int main() {
    int x = 3;
    if (x = 5) {
        std::cout << "x vale 5\n";
    }
    std::cout << "x agora é " << x << "\n";
}
$ g++ -std=c++23 -Wall -Wextra atrib.cpp -o atrib
atrib.cpp: In function ‘int main()’:
atrib.cpp:5:11: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
    5 |     if (x = 5) {
      |         ~~^~~
$ ./atrib
x vale 5                 « x valia 3, mas o if "deu certo"
x agora é 5              « e ainda estragou o valor de x

O que aconteceu: x = 5 guardou 5 em x e "devolveu" 5. Como 5 não é zero, contou como true. O aviso diz: "sugiro parênteses em volta de uma atribuição usada como valor verdade". Em português claro: "você quis mesmo atribuir aqui? Se foi engano, use ==".

Conserto: if (x == 5).

if (…);: o ponto e vírgula que desliga o if

#include <iostream>

int main() {
    double nota = 4.0;
    if (nota >= 7);
    {
        std::cout << "Aprovada!\n";
    }
}
$ g++ -std=c++23 -Wall -Wextra pontovirgula.cpp -o pontovirgula
pontovirgula.cpp: In function ‘int main()’:
pontovirgula.cpp:5:19: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body]
    5 |     if (nota >= 7);
      |                   ^
pontovirgula.cpp:5:5: warning: this ‘if’ clause does not guard... [-Wmisleading-indentation]
    5 |     if (nota >= 7);
      |     ^~
pontovirgula.cpp:6:5: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘if’
    6 |     {
      |     ^
$ ./pontovirgula
Aprovada!                « com nota 4!

Aquele ; sozinho é uma instrução vazia, e é ela que o if controla. O bloco { … } logo abaixo virou um bloco comum, que roda sempre. O primeiro aviso, do -Wextra, diz: "sugiro chaves em volta do corpo vazio de um if". O segundo é o mesmo da seção 4.

Conserto: apague o ; do fim da linha do if.


6. if com inicializador C++17

Às vezes você calcula um valor só para testá-lo no if e usá-lo dentro dele. Desde o C++17, dá para criar essa variável dentro dos parênteses do if, antes da condição, separada por ;:

#include <iostream>

int main() {
    int pontos = 4;

    if (int falta = 10 - pontos; falta > 0) {
        std::cout << "Faltam " << falta << " pontos para o prêmio.\n";
    } else {
        std::cout << "Prêmio liberado! Sobraram " << -falta << " pontos.\n";
    }
}
int falta = 10 - pontos;
O inicializador: cria a variável falta (aqui, 6). Termina com ;.
falta > 0
A condição de sempre, que já pode usar falta.
Dentro do if e do else
falta existe nos dois blocos.
Depois do if
falta deixa de existir. Esse é o objetivo: a variável só vive onde é útil, e não "polui" o resto do programa (aula Escopo).
$ g++ -std=c++23 -Wall -Wextra inicial.cpp -o inicial
$ ./inicial
Faltam 6 pontos para o prêmio.

Tentar usar falta depois do if dá erro:

$ g++ -std=c++23 -Wall -Wextra inicial2.cpp -o inicial2      « std::cout << falta; depois do if
inicial2.cpp: In function ‘int main()’:
inicial2.cpp:9:18: error: ‘falta’ was not declared in this scope
    9 |     std::cout << falta << "\n";
      |                  ^~~~~

"falta não foi declarada neste escopo": para o compilador, fora do if ela nunca existiu. Com um padrão antigo, como -std=c++14, o g++ aceita mas avisa: warning: init-statement in selection statements only available with ‘-std=c++17’ or ‘-std=gnu++17’ [-Wc++17-extensions]. O jeito antigo era declarar a variável na linha de cima do if; também funciona, mas ela continua existindo até o fim do bloco de fora.


Formas diferentes + qual usar

FormaExemploQuando usar
if com chavesif (c) { … }Sempre. É o padrão deste guia.
if sem chavesif (c) x = 0;Só uma instrução, na mesma linha. Evite: convida ao bug da seção 4.
if / elseif (c) { … } else { … }Dois caminhos.
else ifif (…) {…} else if (…) {…} else {…}Três ou mais caminhos. Aula else if.
Ternárioc ? a : bEscolher entre dois valores numa linha. Aula Operador Ternário.
switchswitch (opcao) { case 1: … }Comparar uma variável com uma lista de valores fixos. Aula switch.
if com inicializadorif (int r = f(); r > 0)Quando a variável só é útil para o if.

Quando dá errado

warning: this ‘if’ clause does not guard... [-Wmisleading-indentation]

O que significa: o if não tem chaves, e uma linha recuada como se estivesse dentro dele, na verdade, está fora. Ou há um ; logo depois do ).

Como consertar: ponha chaves em volta de todas as linhas que devem depender da condição, e confira se não há ; depois do ).

warning: suggest parentheses around assignment used as truth value [-Wparentheses]

O que significa: há um = (atribuição) dentro da condição. Quase sempre, você queria ==.

Como consertar: troque por ==.

error: ‘else’ without a previous ‘if’
    if (nota >= 7);
        std::cout << "Aprovada!\n";
    else
        std::cout << "Recuperação.\n";
$ g++ -std=c++23 -Wall -Wextra elsesolto.cpp -o elsesolto
…(os dois avisos de -Wempty-body e -Wmisleading-indentation)…
elsesolto.cpp:7:5: error: ‘else’ without a previous ‘if’
    7 |     else
      |     ^~~~

O que significa: "else sem um if antes". Um else precisa vir imediatamente depois da instrução (ou do bloco) do if. Aqui, o if terminou no ;, depois veio o cout (fora do if), e o else ficou sem par. O mesmo erro aparece quando há duas linhas entre um if sem chaves e o else.

Como consertar: tire o ; depois do ) e use chaves nos dois blocos.

error: ‘falta’ was not declared in this scope

O que significa: você usou fora do if (ou fora das chaves) uma variável criada dentro dele.

Como consertar: se precisa do valor depois, declare a variável antes do if.

Comparar double com == dá "falso" quando deveria dar "verdadeiro"

O que significa: 0.1 + 0.2 == 0.3 é false, porque os números com vírgula são guardados com pequenos erros (aula float e double).

Como consertar: com double, prefira <, >= etc. Para "igual", compare a diferença com uma margem: if (std::abs(a - b) < 0.0001) (veja Matemática).


Referência rápida

EscritaO que faz
if (cond) { … }Roda o bloco só se cond for verdadeira
if (cond) { … } else { … }Um bloco ou o outro, nunca os dois
if (int v = …; cond) { … }Cria v só para o if/else (C++17)
== / =Compara / atribui. No if, quase sempre ==
if (x) com número0 é falso; qualquer outro, verdadeiro
-Wall -WextraLiga os avisos -Wmisleading-indentation, -Wparentheses e -Wempty-body

Exercícios

1. Complete o if

Complete para mostrar "Pode votar" se a idade for 16 ou mais:

(idade 16) { std::cout << "Pode votar\n"; }

2. Senão

Complete com a palavra que dá o caminho alternativo:

if (saldo >= preco) { comprar(); } { avisar(); }

3. Com int x = 0;, o que mostra if (x = 1) { std::cout << "A"; } else { std::cout << "B"; }?

4. Com nota 3, o que este código mostra? if (nota >= 7) std::cout << "A"; std::cout << "B";

5. Em if (int r = 10 % 3; r == 1) { … }, onde a variável r pode ser usada?

Missão final: o frete grátis

Missão: a lojinha da Ana dá frete grátis em compras de R$ 100 ou mais. Usando um if com inicializador (if (double falta = …; …)), mostre Faltam R$ 17.50 para o frete grátis. quando faltar dinheiro, e Frete grátis! no else. Depois, mude o total para 120 e confira o outro caminho. Para as duas casas, use std::println com {:.2f} (aula std::format e std::print).

#include <print>

int main() {
    double total = 82.5;
    // escreva o if aqui
}
#include <print>

int main() {
    double total = 82.5;
    if (double falta = 100 - total; falta > 0) {
        std::println("Faltam R$ {:.2f} para o frete grátis.", falta);
    } else {
        std::println("Frete grátis!");
    }
}

Resumo

  • if (condição) { … } roda o bloco só se a condição for verdadeira. else { … } roda no caso contrário.
  • A condição vai entre parênteses e resulta em true/false. Números também servem (0 = falso), mas prefira comparações explícitas.
  • Use sempre chaves: sem elas, o if controla uma linha só, e a segunda linha roda sempre (-Wmisleading-indentation).
  • if (x = 5) atribui em vez de comparar (-Wparentheses). if (…); desliga o if (-Wempty-body).
  • if (int v = …; v > 0) C++17 cria uma variável que só existe dentro do if/else.
  • Compile sempre com -Wall -Wextra: os três avisos desta aula pegam bugs reais.