int, float, double, char, bool — tipagem estática, memória e comparação com Java
Uma variável é um espaço reservado na memória do computador que recebe um nome e armazena um valor que pode ser alterado durante a execução do programa. Em C, antes de usar qualquer variável, é obrigatório declará-la indicando seu tipo de dado.
A sintaxe básica de declaração é:
tipo nomeDaVariavel; // declaração tipo nomeDaVariavel = valorInicial; // declaração com inicialização
Exemplos práticos:
int idade = 25; // inteiro float altura = 1.75; // ponto flutuante simples double massa = 70.345; // ponto flutuante duplo char inicial = 'A'; // caractere único
Os tipos inteiros armazenam números sem parte fracionária. C oferece quatro variações, com diferentes tamanhos e faixas de valores:
| Tipo | Tamanho típico | Faixa de valores (signed) | Uso típico |
|---|---|---|---|
short |
2 bytes (16 bits) | −32.768 a 32.767 | Contadores pequenos, economia de memória |
int |
4 bytes (32 bits) | −2.147.483.648 a 2.147.483.647 | Uso geral — o tipo inteiro padrão |
long |
4 ou 8 bytes | Depende da plataforma | Inteiros grandes em sistemas 32-bit |
long long |
8 bytes (64 bits) | −9,2 × 10¹⁸ a 9,2 × 10¹⁸ | Valores muito grandes (IDs, timestamps) |
unsigned, que elimina os valores negativos e dobra o limite superior. Exemplo: unsigned int vai de 0 a 4.294.967.295.
#include <stdio.h>
int main() {
short s = 30000;
int i = 2000000;
long l = 2000000000L; // sufixo L para long
long long ll = 9000000000LL; // sufixo LL para long long
unsigned int ui = 4000000000U; // sufixo U para unsigned
printf("short: %d\n", s);
printf("int: %d\n", i);
printf("long: %ld\n", l); // %ld para long
printf("long long: %lld\n", ll); // %lld para long long
printf("unsigned: %u\n", ui); // %u para unsigned int
return 0;
}
short: 30000
int: 2000000
long: 2000000000
long long: 9000000000
unsigned: 4000000000
int um valor maior que 2.147.483.647, o resultado é indefinido (ou "estoura" para um número negativo). C não lança exceção nem avisa — o erro fica silencioso. Use long long quando houver risco de valores grandes.
Os tipos de ponto flutuante armazenam números com parte fracionária. C oferece três variações com diferentes precisões:
| Tipo | Tamanho | Dígitos de precisão | Especificador |
|---|---|---|---|
float |
4 bytes | ~6–7 dígitos significativos | %f |
double |
8 bytes | ~15–16 dígitos significativos | %lf (scanf) / %f (printf) |
long double |
10–16 bytes | ~18–19 dígitos significativos | %Lf |
#include <stdio.h>
int main() {
float f = 3.14159f; // sufixo f para float literal
double d = 3.141592653589793;
float altura = 1.75;
printf("float: %.5f\n", f); // %.5f = 5 casas decimais
printf("double: %.15f\n", d); // mostra a maior precisão do double
printf("altura: %.2f m\n", altura);
return 0;
}
float: 3.14159
double: 3.141592653589793
altura: 1.75 m
double — ele é o padrão em C para literais de ponto flutuante (ex: 3.14 é double por padrão). Use float apenas quando memória for crítica (ex: sistemas embarcados com muitos dados).
O tipo char armazena um único caractere usando a codificação ASCII. Ocupa exatamente 1 byte (8 bits) de memória. Na prática, um char é um número inteiro pequeno — cada caractere tem um código numérico correspondente.
#include <stdio.h>
int main() {
char letra = 'A';
char digito = '7';
printf("Caractere: %c\n", letra); // imprime: A
printf("Código ASCII: %d\n", letra); // imprime: 65 (%d lê o char como inteiro)
printf("Próxima letra: %c\n", letra + 1); // imprime: B (65+1 = 66)
return 0;
}
Caractere: A
Código ASCII: 65
Próxima letra: B
char e int são compatíveis. É válido fazer aritmética com char, como letra + 1. Isso é muito útil para percorrer alfabetos, comparar caracteres e processar texto.
| Código | Caractere | Código | Caractere | Código | Caractere |
|---|---|---|---|---|---|
| 48–57 | '0'–'9' | 65–90 | 'A'–'Z' | 97–122 | 'a'–'z' |
| 32 | espaço | 10 | \n (newline) | 0 | \0 (nulo) |
Ao contrário do Java, que possui o tipo primitivo boolean com os valores true e false, o C originalmente não tinha um tipo booleano. A lógica booleana era implementada com inteiros:
0 representa falso// C antes do C99 — usando int para lógica booleana int ativo = 1; // verdadeiro int inativo = 0; // falso if (ativo) { printf("Sistema ativo!\n"); // este bloco executa }
A partir do padrão C99, foi introduzido o header <stdbool.h>, que define o tipo bool e as constantes true e false formalmente:
#include <stdio.h> #include <stdbool.h> // necessário para usar bool em C99+ int main() { bool aprovado = true; bool reprovado = false; if (aprovado) { printf("Aluno aprovado!\n"); } printf("Valor de true: %d\n", true); // imprime 1 printf("Valor de false: %d\n", false); // imprime 0 return 0; }
Aluno aprovado!
Valor de true: 1
Valor de false: 0
<stdbool.h>, bool em C continua sendo implementado como inteiro por baixo dos panos. Ao contrário do Java, C não impede o uso de inteiros em expressões booleanas — o que pode causar bugs sutis se o programador não tiver cuidado.
O operador sizeof retorna o número de bytes que um tipo ou variável ocupa na memória. É muito útil para entender como o C aloca espaço e para escrever código portável entre diferentes plataformas e sistemas operacionais.
#include <stdio.h>
int main() {
printf("char: %zu byte(s)\n", sizeof(char));
printf("short: %zu byte(s)\n", sizeof(short));
printf("int: %zu byte(s)\n", sizeof(int));
printf("long: %zu byte(s)\n", sizeof(long));
printf("long long: %zu byte(s)\n", sizeof(long long));
printf("float: %zu byte(s)\n", sizeof(float));
printf("double: %zu byte(s)\n", sizeof(double));
printf("long double: %zu byte(s)\n", sizeof(long double));
return 0;
}
char: 1 byte(s)
short: 2 byte(s)
int: 4 byte(s)
long: 8 byte(s)
long long: 8 byte(s)
float: 4 byte(s)
double: 8 byte(s)
long double: 16 byte(s)
sizeof é %zu (z = tamanho, u = unsigned). Em sistemas antigos, pode-se usar %lu como alternativa.
O programa abaixo, baseado no material de referência do curso, demonstra como declarar, inicializar e ler variáveis dos três tipos principais. Observe o uso de <locale.h> para suporte a acentos:
#include <stdio.h> #include <locale.h> // necessário para exibir caracteres acentuados void main() { setlocale(LC_ALL, ""); // ativa o suporte à língua local (acentos) printf("Olá \n"); // ── Inteiro ─────────────────────────────────── int a = 50; printf("O valor de a é = %d \n", a); printf("Informe o novo valor de a: "); scanf("%d", &a); printf("O valor de a mudou para %d \n", a); // ── Ponto flutuante ─────────────────────────── float b = 5.5; printf("O valor de b é = %f \n", b); printf("Informe o novo valor de b: "); scanf("%f", &b); printf("O valor de b mudou para %f \n", b); // ── Caractere ───────────────────────────────── char letra = 't'; printf("O valor de c é = %c \n", letra); printf("Informe o novo valor de c (letra): "); scanf(" %c", &letra); // espaço antes de %c descarta o '\n' do buffer printf("O valor de c mudou para %c\n", letra); }
int b = 5.5 intencionalmente para ilustrar um erro comum: atribuir um valor com casas decimais a um int. O compilador trunca silenciosamente o valor para 5. Para armazenar 5.5 corretamente, use float ou double.
Quando valores de tipos diferentes são combinados em uma expressão, o C realiza conversões de tipo — de forma automática (implícita) ou forçada pelo programador (explícita).
O C promove automaticamente o tipo "menor" para o tipo "maior" em uma expressão:
int i = 7; double d = 2.5; double resultado = i + d; // i é promovido para double automaticamente printf("%.1f\n", resultado); // 9.5
Para forçar uma conversão, use o operador de cast (tipo) antes do valor:
#include <stdio.h>
int main() {
int a = 7, b = 2;
// sem cast: divisão inteira (descarta o resto)
printf("Sem cast: %d\n", a / b); // 3
// com cast: converte a para double antes de dividir
printf("Com cast: %.1f\n", (double)a / b); // 3.5
return 0;
}
Sem cast: 3
Com cast: 3.5
double → int) sem um cast explícito. Em C, essas conversões podem ocorrer silenciosamente, produzindo resultados inesperados sem qualquer aviso por padrão. É uma das razões pelas quais C oferece mais controle — mas também mais responsabilidade — ao programador.
A tabela abaixo compara os tipos primitivos das duas linguagens. As semelhanças são grandes — a principal diferença está no que não existe em C:
| Tipo em C | Equivalente em Java | Diferença principal |
|---|---|---|
int |
int |
Idênticos em comportamento |
short |
short |
Idênticos |
long long |
long |
Em C, long pode ter 4 ou 8 bytes; long long garante 8 |
float |
float |
Idênticos |
double |
double |
Idênticos |
char |
char |
Em C, char é um inteiro de 1 byte; em Java, char é Unicode de 2 bytes |
bool (C99+) |
boolean |
Em C, é apenas um inteiro; em Java, é um tipo separado e não se mistura com inteiros |
| — (não existe) | String |
Em C, strings são arrays de char terminados em \0 — não há tipo String nativo |
| — (não existe) | byte |
Em C, usa-se unsigned char para o mesmo propósito |
Responda às questões abaixo para fixar os tipos de dados em C: