int a = 10;
if (a == 10) {
printf("It's A\n");
a = 20;
}
printf("a = %d\n", a);
O que isso imprime?
It's A a = 20
It's A a = 10
a = 20
Explicação:a==10 é verdadeiro → o corpo do if é executado → "It's A" é impresso → a é definido como 20 → o printf final mostra o valor atual (20).
Questão 2 — Pegadinha de if(a=10)
int a = 3;
if (a = 10) { // = é atribuição! (queria ==)printf("entered\n");
}
printf("a = %d\n", a);
O que isso imprime?
a = 3 (o corpo do if é pulado)
entered a = 10
Erro de compilação
Explicação:a = 10 é uma expressão de atribuição, e seu valor é 10 (diferente de zero, logo "verdadeiro"). O corpo do if é então executado, e a agora é 10, então o print final mostra a = 10.
O C não trata isso como erro por padrão (no máximo você recebe um aviso), e é por isso que é uma fonte clássica de bugs.
Questão 3 — Combinando E e OU
int x = 5;
if (x > 0 && x < 10 || x == 100) {
printf("OK\n");
}
O que isso imprime?
OK
(nada)
Erro de compilação
Explicação:&& tem precedência maior que ||, então isso equivale a (x>0 && x<10) || x==100.
Com x=5: (5>0 && 5<10) é verdadeiro → a expressão toda é verdadeira → "OK" é impresso. Quando estiver em dúvida sobre precedência, adicione parênteses para deixar a intenção clara.
Questão 4 — O básico de if-else
int n = 7;
if (n > 5) {
printf("big\n");
} else {
printf("small\n");
}
O que isso imprime?
big
small
big small (ambos)
(nada)
Explicação: Se a condição é verdadeira, o bloco if é executado; senão, o bloco else é executado — exatamente um dos dois é executado.
n=7 faz n > 5 ser verdadeiro → "big" é impresso, e o ramo else é pulado.
Questão 5 — Escada else if
Verifique várias condições em ordem. Apenas o primeiro ramo verdadeiro é executado.
int score = 75;
if (score >= 90) {
printf("A\n");
} else if (score >= 70) {
printf("B\n");
} else if (score >= 50) {
printf("C\n");
} else {
printf("D\n");
}
O que isso imprime?
A
B
C
B C (ambos combinam)
Explicação: Numa escada else-if, a avaliação para assim que um ramo é verdadeiro.
score=75 não é ≥ 90 → a verificação seguinte >=70 é verdadeira → "B" é impresso → as condições restantes nunca são avaliadas.
As condições podem se sobrepor (são avaliadas de cima para baixo), então por convenção você coloca a mais restritiva primeiro.
Questão 6 — if sem chaves (uma armadilha)
Sem chaves { }, até onde vai o "alcance" do if?
int a = 5;
if (a > 10)
printf("big\n");
printf("always\n"); // cuidado com a indentação enganosa!
O que isso imprime?
always (só uma linha)
(nada)
big always
big
Explicação: Sem chaves, um if executa condicionalmente apenas o único comando que vem logo depois dele.
Com a=5, a condição é falsa → printf("big"); é pulado.
O segundo printf("always"); fica fora do if, então sempre é executado — "always" é impresso (não se deixe enganar pela indentação!). Lição: Sempre use chaves, mesmo quando o corpo for um único comando. Assim, adicionar uma segunda linha depois não introduz bugs silenciosamente.
Questão 7 — Comparando ponto flutuante com ==
Matematicamente, 0.1 + 0.2 = 0.3. Isso ainda é verdade em C?
double x = 0.1 + 0.2;
if (x == 0.3) {
printf("equal\n");
} else {
printf("not equal\n");
}
O que isso imprime?
equal
not equal
Erro de compilação
Explicação: Números de ponto flutuante são armazenados em binário, então 0.1 e 0.2 não podem ser representados exatamente.
O valor real de 0.1 + 0.2 dá 0.30000000000000004..., que não é exatamente 0.3. Resultado: not equal. Lição: Não compare doubles com ==. Em vez disso, trate dois valores como iguais quando a diferença absoluta for pequena (ex.: fabs(x - 0.3) < 1e-9).
Questão 8 — Avaliação em curto-circuito (protegendo contra divisão por zero)
Quando o lado esquerdo de && é falso, o lado direito não é avaliado. Podemos usar isso para evitar dividir por zero?
int a = 10, b = 0;
if (b != 0 && a / b > 5) {
printf("OK\n");
} else {
printf("skip\n");
}
O que acontece?
"OK" é impresso
"skip" é impresso (não ocorre divisão por zero)
Trava com erro de divisão por zero
Erro de compilação
Explicação:&& usa avaliação em curto-circuito. Assim que o lado esquerdo b != 0 é falso, o lado direito a / bnem é avaliado.
Nenhuma divisão por zero acontece, então o ramo else imprime "skip". Padrão: Escrever "verificação de segurança && condição principal" cria uma proteção que evita o erro.
Obs.: se você inverter a ordem para a / b > 5 && b != 0, a divisão acontece primeiro e você cai no erro de divisão por zero. Sempre coloque a verificação de segurança primeiro.
Questão 9 — E se nenhum ramo combinar e não houver else?
Com apenas if / else if (sem else final), o que acontece quando nenhuma condição é verdadeira?
int x = 100;
if (x < 0) {
printf("negative\n");
} else if (x < 10) {
printf("small\n");
} else if (x < 50) {
printf("medium\n");
}
printf("done\n");
O que isso imprime?
medium done
done
(nada)
Erro de compilação
Explicação: x=100 não satisfaz nenhuma das condições (<0, <10, <50). Sem else, o bloco if simplesmente não faz nada e segue adiante.
O printf("done"); seguinte fica fora do if, então sempre é executado — só "done" é impresso. Lição: Se você precisa de um caso "nenhum dos anteriores", escreva um else. Deixar de fora significa "não fazer nada quando nada combina".
Questão 10 — ifs independentes vs else if
Esses dois padrões parecem similares, mas se comportam de forma diferente. Compare os dois trechos abaixo.
// Padrão A: ligados com else ifint n = 50;
if (n > 0) {
printf("positive\n");
} else if (n > 30) {
printf("large\n");
}
// Padrão B: dois ifs independentesif (n > 0) {
printf("positive\n");
}
if (n > 30) {
printf("large\n");
}
O que cada um imprime quando n=50?
A: positive / B: positive
A: positive / B: positive large
A: positive large / B: positive large
A: positive large / B: positive
Explicação: Essa é a diferença principal entre else if e ifs independentes. Padrão A (else if): Só o primeiro ramo verdadeiro é executado. n=50 faz n>0 ser verdadeiro → imprime "positive" e para (n>30 nunca é verificado). Padrão B (dois ifs independentes): Cada um é avaliado independentemente. n>0 é verdadeiro → "positive"; depois n>30 também é verdadeiro → "large". Ambas as linhas são impressas. Qual usar? "Rodar exatamente um" → else if. "Verificar os dois de forma independente" → ifs separados.
Questão 11 — O else final é um "pega-tudo"
O else final em uma escada else-if é executado sempre que todas as condições anteriores forem falsas.
int grade = -5;
if (grade >= 90) {
printf("Excellent\n");
} else if (grade >= 70) {
printf("Good\n");
} else if (grade >= 50) {
printf("Pass\n");
} else {
printf("Fail\n");
}
O que imprime quando grade=-5 (valor negativo)?
Excellent
Pass
(nada)
Fail
Explicação: -5 falha em >=90, >=70 e >=50, então o else final é executado e "Fail" é impresso.
O else final captura tudo que não combinou com nenhuma condição anterior — é o pega-tudo. Lição: Adicionar um else te dá tranquilidade de que valores inesperados (como -5 ou 999) ainda serão tratados em algum lugar.
Questão 12 — dangling else (a qual if pertence o else?)
Quando as chaves são omitidas, a qual if o else realmente pertence?
int a = 5, b = 10;
if (a > 0)
if (b > 20)
printf("both big\n");
elseprintf("b is small\n");
O que isso imprime? (a indentação é irrelevante)
both big
b is small
(nada)
Erro de compilação
Explicação: A regra é que o else se liga ao if mais próximo (regra do dangling else).
A indentação faz parecer que o else pertence ao if externo, mas na verdade é o else do if (b > 20) interno.
a=5 (então a > 0 é verdadeiro) → entra no if interno → b=10 faz b > 20 ser falso → o ramo else imprime "b is small". Lição: Com ifs aninhados, use chaves sempre. Elas eliminam completamente a ambiguidade.
Questão 13 — Um bug de classificação de notas (múltiplos ifs vs else if)
Queremos classificar uma pontuação como A / B / C. Aqui está um bug clássico.
// Código com bug: três ifs independentesint score = 85;
if (score >= 90) {
printf("A\n");
}
if (score >= 70) {
printf("B\n");
}
if (score >= 50) {
printf("C\n");
}
O que imprime quando score=85?
A
B
B C
A B C
Explicação: Como os ifs são independentes, cada bloco cuja condição é verdadeira é executado.
Com score=85: ≥90 é falso → pulado / ≥70 é verdadeiro → "B" / ≥50 também é verdadeiro → "C". Resultado: B e C são impressos.
Forma correta (use else if):
if (score >= 90) {
printf("A\n");
} else if (score >= 70) {
printf("B\n");
} else if (score >= 50) {
printf("C\n");
}
Agora a cadeia else-if executa apenas o primeiro ramo que combina, então score=85 imprime só "B".
Como escolher:
Condições mutuamente exclusivas (só uma deve se aplicar) → use else if.
Condições independentes (ambas podem ser verdadeiras e ambas devem rodar) → use ifs separados.