Operadores e Expressões

Operadores são como utensílios de cozinha — você usa uma faca para cortar e uma frigideira para fritar. Ingredientes diferentes precisam de ferramentas diferentes, e cálculos diferentes precisam de operadores diferentes.

Operadores Aritméticos

C fornece 7 operadores aritméticos básicos para os cálculos matemáticos mais comuns.

Operador Significado Exemplo Resultado
+ Adição 5 + 3 8
- Subtração 5 - 3 2
* Multiplicação 5 * 3 15
/ Divisão 7 / 2 3
% Módulo (resto) 7 % 2 1
+ Mais unário +5 5
- Menos unário -5 -5

A Armadilha da Divisão Inteira

Quando dois inteiros são divididos, o resultado também é inteiro — a parte fracionária é simplesmente descartada, não arredondada.

C
#include <stdio.h>

int main(void) {
    int a = 7;
    int b = 2;
    printf("%d / %d = %d\n", a, b, a / b);
    printf("%d %% %d = %d\n", a, b, a % b);
    return 0;
}
TEXT
7 / 2 = 3
7 % 2 = 1
💡 Dica: Para obter um resultado com decimais, faça pelo menos um operando ser float: 7.0 / 23.5.

Usos do Operador de Módulo

O operador de módulo % só funciona com inteiros. Tem vários casos de uso muito práticos:

C
#include <stdio.h>

int main(void) {
    int n = 12345;
    printf("Último dígito: %d\n", n % 10);
    printf("É par: %s\n", n % 2 == 0 ? "Sim" : "Não");
    return 0;
}
TEXT
Último dígito: 5
É par: Não

Operadores de Incremento e Decremento

O operador de incremento ++ adiciona 1 a uma variável, e -- subtrai 1. Cada um vem em duas formas: prefixo e sufixo, que diferem no valor que a expressão retorna.

Prefixo vs. Sufixo

Forma Nome Efeito Valor da Expressão
++i Incremento prefixo i aumenta 1 O novo valor (aumentado)
i++ Incremento sufixo i aumenta 1 O valor antigo (original)
--i Decremento prefixo i diminui 1 O novo valor (diminuído)
i-- Decremento sufixo i diminui 1 O valor antigo (original)
C
#include <stdio.h>

int main(void) {
    int a = 5;
    int b = ++a;
    printf("Prefixo: a=%d, b=%d\n", a, b);

    int c = 5;
    int d = c++;
    printf("Sufixo: c=%d, d=%d\n", c, d);
    return 0;
}
TEXT
Prefixo: a=6, b=6
Sufixo: c=6, d=5
⚠️ Atenção: Não use ++ ou -- na mesma variável múltiplas vezes dentro de uma expressão, como a = ++a + a++. O comportamento é indefinido, e compiladores diferentes darão resultados diferentes.

Operadores Relacionais

Operadores relacionais comparam dois valores, retornando "verdadeiro" (1) ou "falso" (0).

Operador Significado Exemplo Resultado
== Igual a 5 == 5 1
!= Diferente de 5 != 3 1
< Menor que 3 < 5 1
> Maior que 3 > 5 0
<= Menor ou igual 5 <= 5 1
>= Maior ou igual 3 >= 5 0
C
#include <stdio.h>

int main(void) {
    int a = 10;
    int b = 20;
    printf("a == b: %d\n", a == b);
    printf("a != b: %d\n", a != b);
    printf("a < b:  %d\n", a < b);
    return 0;
}
TEXT
a == b: 0
a != b: 1
a < b:  1
⚠️ Atenção: == é comparação, = é atribuição. Confundir os dois transforma a comparação em uma atribuição que não vai gerar erro. Um bom hábito é colocar a constante à esquerda: 5 == a — se você acidentalmente escrever 5 = a, o compilador vai detectar.

Operadores Lógicos

Operadores lógicos combinam múltiplas condições, também retornando 1 (verdadeiro) ou 0 (falso).

Operador Significado Exemplo Resultado
&& E lógico 1 && 0 0
` ` OU lógico
! NÃO lógico !0 1

Tabela-Verdade

| A | B | A && B | A || B | !A | |---|---|--------|--------|----| | 0 | 0 | 0 | 0 | 1 | | 0 | 1 | 0 | 1 | 1 | | 1 | 0 | 0 | 1 | 0 | | 1 | 1 | 1 | 1 | 0 |

Avaliação de Curto-Circuito

Com &&, se o lado esquerdo for falso, o lado direito nunca é avaliado. Com ||, se o lado esquerdo for verdadeiro, o lado direito é ignorado. Esse recurso pode ser usado para evitar operações ilegais:

C
#include <stdio.h>

int main(void) {
    int divisor = 0;
    int valor = 10;
    if (divisor != 0 && valor / divisor > 5) {
        printf("Condição atendida\n");
    } else {
        printf("Condição não atendida, sem divisão por zero\n");
    }
    return 0;
}
TEXT
Condição não atendida, sem divisão por zero
💡 Dica: Em C, 0 é falso e qualquer valor diferente de zero é verdadeiro (incluindo negativos). Então -5 é "verdadeiro" em um contexto lógico.

Operadores de Atribuição

O operador de atribuição básico = armazena o valor do lado direito na variável do lado esquerdo. C também fornece operadores de atribuição composta que combinam uma operação com atribuição.

Composto Equivalente
a += b a = a + b
a -= b a = a - b
a *= b a = a * b
a /= b a = a / b
a %= b a = a % b
C
#include <stdio.h>

int main(void) {
    int pontuacao = 80;
    pontuacao += 10;
    printf("Após bônus: %d\n", pontuacao);
    pontuacao -= 25;
    printf("Após penalidade: %d\n", pontuacao);
    pontuacao *= 2;
    printf("Após dobrar: %d\n", pontuacao);
    return 0;
}
TEXT
Após bônus: 90
Após penalidade: 65
Após dobrar: 130

O Operador Condicional (Operador Ternário)

O operador condicional ?: é o único operador ternário de C. Sua sintaxe é:

TEXT
condição ? expressão1 : expressão2

Se a condição for verdadeira, expressão1 é avaliada; caso contrário, expressão2 é avaliada. É uma abreviação de if-else.

C
#include <stdio.h>

int main(void) {
    int idade = 20;
    char *status = idade >= 18 ? "Adulto" : "Menor";
    printf("Idade %d, %s\n", idade, status);

    int a = 15, b = 28;
    int max = a > b ? a : b;
    printf("Maior valor: %d\n", max);
    return 0;
}
TEXT
Idade 20, Adulto
Maior valor: 28

O Operador Vírgula

O operador vírgula , avalia cada expressão da esquerda para a direita, e o valor de toda a expressão vírgula é o valor da última expressão.

C
#include <stdio.h>

int main(void) {
    int a, b, c;
    c = (a = 1, b = 2, a + b);
    printf("a=%d, b=%d, c=%d\n", a, b, c);
    return 0;
}
TEXT
a=1, b=2, c=3
⚠️ Atenção: O operador vírgula tem a menor precedência de todos os operadores. Não confunda o operador vírgula com as vírgulas entre argumentos de função — essas não são operadores vírgula.

O Operador sizeof

sizeof retorna o número de bytes que um tipo de dado ou variável ocupa na memória. É avaliado em tempo de compilação, não em tempo de execução.

C
#include <stdio.h>

int main(void) {
    printf("char:   %zu bytes\n", sizeof(char));
    printf("int:    %zu bytes\n", sizeof(int));
    printf("float:  %zu bytes\n", sizeof(float));
    printf("double: %zu bytes\n", sizeof(double));

    int arr[5] = {1, 2, 3, 4, 5};
    printf("Tamanho total do array: %zu bytes\n", sizeof(arr));
    printf("Quantidade de elementos: %zu\n", sizeof(arr) / sizeof(arr[0]));
    return 0;
}
TEXT
char:   1 bytes
int:    4 bytes
float:  4 bytes
double: 8 bytes
Tamanho total do array: 20 bytes
Quantidade de elementos: 5
💡 Dica: sizeof exige parênteses para nomes de tipos (sizeof(int)) mas não para variáveis (sizeof a). Porém, por consistência, é melhor sempre usar parênteses.

Precedência de Operadores

Quando uma expressão contém múltiplos operadores, o de maior precedência é avaliado primeiro. A tabela abaixo lista da maior para a menor:

Precedência Operadores Associatividade
1 (maior) () [] -> . Esquerda para direita
2 ! ~ ++ -- +(unário) -(unário) *(dereferência) &(endereço) sizeof Direita para esquerda
3 * / % Esquerda para direita
4 + - Esquerda para direita
5 << >> Esquerda para direita
6 < <= > >= Esquerda para direita
7 == != Esquerda para direita
8 & Esquerda para direita
9 ^ Esquerda para direita
10 ` `
11 && Esquerda para direita
12 `
13 ?: Direita para esquerda
14 = += -= *= /= %= etc. Direita para esquerda
15 (menor) , Esquerda para direita
🔥 Erro Comum: Não consegue memorizar a tabela de precedência? Não se preocupe — na dúvida, adicione parênteses. Eles sempre têm a prioridade mais alta e tornam seu código mais claro.

Exemplo

Combine vários operadores para calcular a soma de cada dígito de um número de três dígitos:

C
#include <stdio.h>

int main(void) {
    int num = 952;
    int centenas = num / 100;
    int dezenas = (num / 10) % 10;
    int unidades = num % 10;
    int soma = centenas + dezenas + unidades;

    printf("Número: %d\n", num);
    printf("Centenas: %d, Dezenas: %d, Unidades: %d\n", centenas, dezenas, unidades);
    printf("Soma dos dígitos: %d\n", soma);
    return 0;
}
▶ Experimente
TEXT
Número: 952
Centenas: 9, Dezenas: 5, Unidades: 2
Soma dos dígitos: 16

Exemplo

Use operadores lógicos e relacionais para determinar se um ano é bissexto:

C
#include <stdio.h>

int main(void) {
    int ano = 2024;
    int e_bissexto = (ano % 4 == 0 && ano % 100 != 0) || (ano % 400 == 0);

    printf("%d %sé bissexto\n", ano, e_bissexto ? "" : "não ");
    return 0;
}
▶ Experimente
TEXT
2024 é bissexto

Conversão de Tipos

Conversão Implícita

Quando tipos diferentes são misturados em uma expressão, o compilador automaticamente converte o tipo de menor precisão para o de maior precisão:

C
#include <stdio.h>

int main(void) {
    int a = 5;
    double b = 2.0;
    double c = a / b;
    printf("5 / 2.0 = %f\n", c);

    char ch = 'A';
    int codigo = ch + 1;
    printf("'A' + 1 = %c (ASCII %d)\n", codigo, codigo);
    return 0;
}
TEXT
5 / 2.0 = 2.500000
'A' + 1 = B (ASCII 66)

Direção de conversão: charintlongdouble, intunsignedlongdouble.

Cast Explícito

Use (nome_do_tipo) para forçar um valor a um tipo específico:

C
#include <stdio.h>

int main(void) {
    int a = 7, b = 2;
    double resultado = (double)a / b;
    printf("Com cast: %f\n", resultado);
    return 0;
}
TEXT
Com cast: 3.500000
⚠️ Atenção: O cast não altera o valor ou tipo da variável original — só produz um novo valor temporário.

❓ Perguntas Frequentes

P: Há diferença entre a++ e ++a quando usados em uma linha própria? R: Não. A diferença só importa quando você usa o valor de retorno dentro de uma expressão. Sozinhos, o efeito é idêntico, embora o incremento prefixo seja teoricamente um pouco mais eficiente.

P: Como não confundir = e ==? R: = é atribuição ("torna-se"), == é comparação ("é igual?"). Escrever if (a = 0) por engano não causa erro mas muda completamente a lógica. Um bom hábito: coloque a constante à esquerda — if (0 == a) — assim um erro de digitação como if (0 = a) será detectado pelo compilador.

P: O operador % pode ser usado com números de ponto flutuante? R: Não. % só funciona com tipos inteiros. Para módulo de ponto flutuante, use a função fmod() de #include <math.h>.

P: Preciso memorizar toda a tabela de precedência de operadores? R: Não. Lembre-se apenas que multiplicação/divisão/módulo vêm antes de adição/subtração, e NÃO lógico vem antes de E lógico antes de OU lógico. Para o resto, adicione parênteses — é mais seguro.

📖 Resumo

📝 Exercícios

  1. Escreva um programa que pegue um número de segundos (ex. 3661) e use / e % para calcular as horas, minutos e segundos correspondentes, depois exiba o resultado.
  2. Escreva um programa que pegue dois inteiros e use o operador ternário para encontrar e exibir o maior e o menor valor.
  3. Escreva um programa que use sizeof para imprimir os tamanhos de short, int, long e long long no seu computador e observe os resultados.
100%