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.
#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;
}
7 / 2 = 3
7 % 2 = 1
7.0 / 2 dá 3.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:
- Verificar par/ímpar:
n % 2igual a 0 significa par - Pegar o último dígito:
n % 10dá a casa das unidades - Indexação circular:
i % tamanhomantém o índice ciclando entre 0 e tamanho-1
#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;
}
Ú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) |
#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;
}
Prefixo: a=6, b=6
Sufixo: c=6, d=5
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 |
#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;
}
a == b: 0
a != b: 1
a < b: 1
== é 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:
#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;
}
Condição não atendida, sem divisão por zero
-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 |
#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;
}
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 é:
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.
#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;
}
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.
#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;
}
a=1, b=2, c=3
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.
#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;
}
char: 1 bytes
int: 4 bytes
float: 4 bytes
double: 8 bytes
Tamanho total do array: 20 bytes
Quantidade de elementos: 5
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 |
Exemplo
Combine vários operadores para calcular a soma de cada dígito de um número de três dígitos:
#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;
}
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:
#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;
}
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:
#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;
}
5 / 2.0 = 2.500000
'A' + 1 = B (ASCII 66)
Direção de conversão: char → int → long → double, int → unsigned → long → double.
Cast Explícito
Use (nome_do_tipo) para forçar um valor a um tipo específico:
#include <stdio.h>
int main(void) {
int a = 7, b = 2;
double resultado = (double)a / b;
printf("Com cast: %f\n", resultado);
return 0;
}
Com cast: 3.500000
❓ Perguntas Frequentes
P: Há diferença entre
a++e++aquando 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?"). Escreverif (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 comoif (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çãofmod()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
- Na aritmética, divisão inteira trunca a parte decimal; módulo só funciona com inteiros
++/--prefixo retorna o novo valor, sufixo retorna o antigo; evite usá-los múltiplas vezes na mesma variável em uma expressão- Operadores relacionais retornam 0 ou 1; cuidado para não confundir
=com== - Operadores lógicos
&&e||fazem curto-circuito, o que pode proteger a expressão do lado direito - Não decore precedência — na dúvida, adicione parênteses
📝 Exercícios
- 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. - Escreva um programa que pegue dois inteiros e use o operador ternário para encontrar e exibir o maior e o menor valor.
- Escreva um programa que use
sizeofpara imprimir os tamanhos deshort,int,longelong longno seu computador e observe os resultados.



