Publicidade

Booleanos em C — truthy e falsy

Em C, 0 é falso e todo o resto é verdadeiro. Uma regra simples com várias armadilhas. Esta página percorre o caminho seguro, incluindo o tipo bool do C99.

Era K&R → bool do C99

O C antigo não tinha tipo booleano. O código dependia inteiramente da regra "0 é falso, qualquer outra coisa é verdadeiro".

Estilo antigo (pré-C99)

int done = 0;         // 0 = falso
while (!done) {
    if (condicao) done = 1;    // 1 = verdadeiro
}

C99 em diante

#include <stdbool.h>   // fornece bool, true, false

bool done = false;
while (!done) {
    if (condicao) done = true;
}
Por baixo dos panos: bool é uma macro para _Bool, e true/false são só 1/0. _Bool é um tipo especial que só armazena 0 ou 1 — atribuir qualquer valor diferente de zero te dá 1.
_Bool b = 42;     // vira 1 (nao 42)
printf("%d\n", b);  // → 1

int i = 42;
printf("%d\n", i);  // → 42

Regras truthy / falsy

Sempre que C testa uma condição — if, while, for, ternário ?: — a regra é:
0 → falso
diferente de zero → verdadeiro
NULL → falso (ponteiro 0)
0.0 → falso (float 0)
if (0)   { // nao entra }
if (-1)  { // entra (diferente de zero eh verdadeiro) }
if (42)  { // entra }
if (0.0) { // nao entra }

char *p = NULL;
if (p)    { // nao entra (NULL eh 0) }
"Verdadeiro" não é um único valor: tanto -1 quanto 42 são truthy. Se você precisa distinguir os dois, compare explicitamente — "igual a 1" não é o mesmo que "é verdadeiro".

Resultado dos operadores de comparação

O resultado de ==, !=, <, >, <= e >= é sempre um int — 0 ou 1, não true/false.
int a = 5, b = 3;
int r = (a > b);   // r == 1 (int)
printf("%d\n", r);  // 1

// Truque util: somar os resultados booleanos direto.
int count = 0;
for (int i = 0; i < n; i++) {
    count += (a[i] > 0);   // conta os elementos positivos
}

Ponteiros e floats

Ponteiros: NULL ou não

char *p = malloc(100);
if (p) {
    // nao NULL → alocacao deu certo
    free(p);
}

// equivalente
if (p)          { /* ... */ }
if (p != NULL) { /* ... */ }
Qual estilo? Bases de código ao estilo K&R preferem if (p); bases que priorizam legibilidade preferem if (p != NULL). É mais uma escolha de estilo de equipe.

Floats: cuidado com == 0.0

❌ Igualdade exata de float

double x = 0.1 + 0.2;
if (x == 0.3) {       // falso!
    // x real ≈ 0.30000000000000004
}

✅ Comparação com epsilon

#include <math.h>

double x = 0.1 + 0.2;
if (fabs(x - 0.3) < 1e-9) {
    // iguais dentro da tolerancia
}
Comparar exatamente com 0.0 é OK (zero é representável). Para valores computados, uma comparação com epsilon é mais segura.

Bugs comuns

Bug 1: if (x == true) é perigoso

int x = 2;           // 2 eh truthy mas nao eh 1

if (x == true) {     // RUIM: true eh 1 → 2 == 1 eh falso
    printf("nao entra\n");
}

if (x) {            // OK: diferente de zero eh verdadeiro
    printf("entra\n");
}
Regra prática: se você está usando um valor como booleano, basta testá-lo direto com if (x) ou if (!x). Nunca compare com true. Se realmente precisa de um 0/1 limpo, use o idioma !!x abaixo.

Bug 2: = vs ==

❌ Atribuição

if (x = 5) {
    // "atribui 5 a x, depois testa 5"
    // sempre verdadeiro
}

✅ Comparação

if (x == 5) {
    // testa igualdade
}
Como evitar: -Wall avisa em if (x = 5). Algumas equipes usam "condições Yoda" (if (5 == x)) para que um typo vire um erro de compilação.

Bug 3: precedência de !

if (!x && y)        // (!x) && y — "x eh falso E y eh verdadeiro"
if (!(x && y))      // "pelo menos um entre x ou y eh falso"
// Significados diferentes — use parenteses na duvida.

Bug 4: bit a bit vs lógico

if (a & b)   // E bit a bit: algum bit comum setado
if (a && b)  // E logico: tanto a quanto b sao truthy

// a = 4 (100), b = 3 (011)
// a & b  → 0 (sem bit comum) → falsy
// a && b → verdadeiro (ambos diferentes de zero)

Idioma: !!x para normalizar para 0/1

Aplicar ! duas vezes reduz qualquer valor a exatamente 0 ou 1.
int x = 42;
int normalized = !!x;   // 42 → !42=0 → !0=1 → 1

int y = 0;
int n2 = !!y;           // 0 → !0=1 → !1=0 → 0

Quando é útil

Uma alternativa mais explícita: bool b = (x != 0); lê melhor. Atribuir a _Bool também normaliza automaticamente, então _Bool b = x; funciona do mesmo jeito.

Avaliação por curto-circuito

&& e || avaliam da esquerda para a direita e param assim que o resultado é determinado.

Exemplo de &&

if (p != NULL && p->value > 0) {
    // se p for NULL, p->value nao eh avaliado (sem crash)
}

Exemplo de ||

if (x == 0 || y / x > 10) {
    // se x for 0, y/x nao eh avaliado (sem divisao por zero)
}
A ordem importa: x == 0 || y / x > 10 é seguro, mas y / x > 10 || x == 0 ainda pode dividir por zero. Sempre coloque a proteção primeiro.

Idiomas com efeitos colaterais

// Chama uma funcao so quando uma flag esta setada.
if (mode_debug && log_debug(msg)) {
    // log_debug roda so quando mode_debug eh truthy
}
Atenção: diferente do JavaScript, o || de C retorna 0 ou 1 — não o valor do operando. Então x = get_value() || 10; não te dá um "valor padrão"; te dá 0 ou 1.

Desafios

Desafio 1: prever e rodar
Preveja a saída de
printf("%d %d %d %d\n", !0, !1, !!5, !!-3);
depois compile e verifique.
Desafio 2: a armadilha if (x == true)
Com int x = 2;, escreva um programa que mostre if (x == true) e if (x) seguindo ramos diferentes.
Desafio 3: igualdade de float
Mostre que 0.1 + 0.2 == 0.3 dá falso, depois conserte com uma comparação por epsilon.
Desafio 4: NULL-safe com curto-circuito
Escreva uma função que recebe um char *s e retorna 1 quando s não é NULL e seu primeiro caractere é 'A'. Use && na ordem certa para evitar uma desreferência de NULL.
Desafio 5: contagem via comparação
Conte quantos elementos de um array de int são ≥ 0 sem usar if — apenas some a expressão de comparação (com valor booleano) dentro de um laço.

Teste de Revisão

Teste seu entendimento desta aula!

Q1. Em C, qual valor é tratado como "falso"?

0
Qualquer número negativo
Qualquer número diferente de 0.0

Só 0 é falso. Qualquer valor diferente de zero, incluindo números negativos, conta como verdadeiro.

Q2. Quais tipos e constantes ficam disponíveis após incluir stdbool.h?

bool, true, false
Boolean, TRUE, FALSE
bit, on, off

Desde o C99, incluir <stdbool.h> te dá bool, true e false.

Q3. Quando if (x) avalia x como verdadeiro?

Quando x é qualquer valor diferente de zero
Só quando x é um inteiro positivo
Só quando x é a constante true

Em C, 0 é falso e qualquer coisa diferente de zero — incluindo números negativos e ponteiros não-NULL — é verdadeiro.