Menu

If else em C: sintaxe, exemplos e erros comuns

Como C decide: a instrução if, o else, cadeias de else if, aninhamento e o operador ternário - além da regra de veracidade (0 é falso, todo o resto é verdadeiro) e do bug de = vs == que quebra condições em silêncio.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

Por que programas precisam de ramos

Todo programa até aqui executou em linha reta: linha 1, linha 2, linha 3. Programas de verdade tomam decisões. A senha está correta? O número é negativo? O arquivo abriu? A instrução if é como C faz uma pergunta e executa código apenas quando a resposta é sim.

A condição temperature > 30 é testada uma vez. Ela vale, então a mensagem é impressa. A última linha está fora das chaves, então ela é impressa aconteça o que acontecer. Mude 31 para 18 e rode de novo - a primeira mensagem some e a segunda fica.

Sintaxe: parênteses, chaves e nenhum ponto e vírgula

Um if em C tem um formato fixo:

if (condition) {
    // executa quando a condição é diferente de zero
}

Três regras que vale memorizar cedo. Os parênteses em volta da condição são obrigatórios. Não existe palavra-chave then. E não há ponto e vírgula depois do parêntese de fechamento - um ponto e vírgula perdido encerra a instrução bem ali:

// BUG: o if não faz nada; o printf sempre executa
if (x > 10);
{
    printf("grande\n");
}

Isso compila limpo. O ; é uma instrução vazia que se torna o corpo do if, e as chaves abaixo são apenas um bloco autônomo que sempre executa. Compilar com gcc -Wall pega o problema.

As chaves em si são opcionais para uma única instrução, mas deixe-as. Um if sem chaves que depois ganha uma segunda linha é uma fonte clássica de bugs, porque a indentação não agrupa instruções em C.

else e else if

else fornece o outro caminho:

Para mais de dois resultados, encadeie com else if. C verifica cada condição em ordem e para na primeira que vale:

A ordem importa enormemente aqui. Como a cadeia para na primeira correspondência, o segundo teste só vê pontuações abaixo de 90 - e é por isso que score >= 80 não precisa dizer também && score < 90. Escreva a cadeia da condição mais restritiva para a menos restritiva, ou todo valor cai no primeiro ramo.

O else final é opcional. Inclua um sempre que a cadeia deva cobrir todos os casos; a ausência dele significa "se nada correspondeu, não faça nada", o que está tudo bem mas deve ser deliberado.

Veracidade: 0 é falso, todo o resto é verdadeiro

A linguagem básica de C não tem um tipo booleano separado nas condições. Um if simplesmente pergunta se a expressão é diferente de zero.

As duas últimas linhas mostram a outra metade da regra: operadores de comparação são expressões comuns que produzem 1 para verdadeiro e 0 para falso. É por isso que if (5 > 2) funciona - na verdade é if (1).

É também por isso que -3 é verdadeiro em C. A regra é diferente de zero, não positivo. Se você quer saber se um número é positivo, escreva if (n > 0), não if (n).

O C99 acrescentou <stdbool.h> com um tipo bool de verdade mais true e false, o que se lê melhor em código novo. Por baixo dos panos eles continuam sendo 1 e 0, então nada da regra acima muda - veja Booleanos em C.

Os operadores de comparação e lógicos que você vai usar em condições:

==   igual a              &&   E lógico (os dois lados verdadeiros)
!=   diferente de         ||   OU lógico (qualquer um dos lados)
<    menor que            !    NÃO lógico
>    maior que
<=   menor ou igual a
>=   maior ou igual a

&& e || fazem curto-circuito: a && b nunca avalia b se a for falso, e a || b nunca avalia b se a for verdadeiro. Isso é uma garantia, não uma otimização, então é seguro escrever if (n != 0 && total / n > 5) - a divisão não pode executar quando n é zero.

O bug de = vs ==

Este é, isoladamente, o erro mais comum em condições em C:

// BUG: atribui 5 a x, depois testa 5 (diferente de zero), então isto SEMPRE executa
if (x = 5) {
    printf("x e cinco\n");
}

C permite atribuição dentro de uma expressão, então a linha é legal. Ela guarda 5 em x, produz o valor 5, e 5 é diferente de zero - o ramo executa todas as vezes, e x foi sobrescrito silenciosamente.

Duas defesas. Primeiro, sempre compile com os avisos ligados:

gcc -Wall -Wextra program.c -o program

GCC e clang ambos sinalizam "suggest parentheses around assignment used as truth value". Segundo, alguns programadores escrevem a constante antes da variável - if (5 == x) - para que um if (5 = x) digitado por engano seja um erro de compilação duro em vez de um bug silencioso. Esse estilo é questão de gosto; ligar os avisos não é.

Aninhamento

Um if pode conter outro if. Aninhar expressa condições que só fazem sentido depois que uma anterior vale:

Dois níveis são legíveis. Quatro não são. Quando o aninhamento fica fundo, procure um jeito de achatá-lo - muitas vezes combinando condições com &&, ou tratando os casos de falha primeiro e retornando cedo:

// mais achatado: trate as exceções, depois siga com o trabalho
if (age < 18)     { printf("Apenas para adultos.\n");        return 0; }
if (!hasTicket)   { printf("Por favor, compre um ingresso.\n"); return 0; }
printf("Bem-vindo.\n");

O else pendurado

Quando um if sem chaves é aninhado dentro de outro, a qual if um else pertence? A regra de C: um else se liga ao if não pareado mais próximo, independentemente de como o código está indentado.

// O else pertence ao if INTERNO, apesar da indentação
if (a > 0)
    if (b > 0)
        printf("ambos positivos\n");
else
    printf("a nao e positivo\n");   // ERRADO - executa quando a > 0 e b <= 0

A indentação diz que o else se emparelha com o if externo. O compilador o emparelha com o interno. As chaves removem a ambiguidade por completo, o que é o verdadeiro argumento para sempre usá-las:

if (a > 0) {
    if (b > 0) {
        printf("ambos positivos\n");
    }
} else {
    printf("a nao e positivo\n");
}

O operador ternário

Quando um ramo existe só para escolher um valor, o operador condicional ? : diz isso em uma expressão:

Leia cond ? x : y como "se cond então x senão y". Exatamente um dos dois ramos é avaliado, e o conjunto todo produz um valor - que é por que ele pode ser atribuído ou passado como argumento onde uma instrução não poderia.

Guarde-o para escolhas simples de valor. Ternários aninhados (a ? b : c ? d : e) são legais e quase sempre mais difíceis de ler do que a cadeia de else if que eles substituem.

Perguntas frequentes

Como se escreve uma instrução if else em C?

Coloque a condição entre parênteses e o código entre chaves: if (score >= 60) { printf("Passou\n"); } else { printf("Reprovou\n"); }. O bloco else executa apenas quando a condição é falsa, e não existe palavra-chave then em C.

O que conta como verdadeiro em um if em C?

Qualquer valor que não seja zero. C não tem um tipo booleano dedicado em sua sintaxe básica, então if (n) executa quando n é qualquer coisa exceto 0, e if (!n) executa apenas quando n é exatamente 0. Operadores de comparação como == e < produzem 1 para verdadeiro e 0 para falso.

Qual é a diferença entre = e == em C?

== compara, = atribui. Escrever if (x = 5) atribui 5 a x e então testa 5, que é diferente de zero, então o ramo sempre executa. Isso compila sem erro, e é por isso que é o bug de iniciante mais comum em condições em C - a maioria dos compiladores avisa sobre ele com -Wall.

Como funciona o operador ternário em C?

condição ? valorSeVerdadeiro : valorSeFalso é uma expressão que produz um de dois valores, então pode ficar dentro de uma atribuição ou de um argumento de printf: int max = a > b ? a : b;. Use-o para escolher um valor, e um if comum quando você precisa executar instruções.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR