Tipos de Dados
Tipo de dado não é detalhe.
Tipo de dado é contrato.
É o que define:
- o que um valor significa
- quanto espaço ele ocupa
- quais operações fazem sentido
- que tipo de bug pode nascer dali
Quando você domina tipos de dados, para de programar só na superfície e começa a entender como a máquina realmente enxerga o que você escreveu.
E isso muda tudo.
Antes de falar de tipos: tudo vira bit
Seção intitulada “Antes de falar de tipos: tudo vira bit”No fim do dia, a memória não sabe o que é int, float, char ou bool.
Ela só guarda bits.
Bit é o menor pedaço de informação digital:
01
Oito bits formam um byte.
1 bit = 0 ou 18 bits = 1 byte1024 bytes = 1 KB1024 KB = 1 MBExemplo de 1 byte:
01000001Esse mesmo byte pode ser interpretado de várias formas:
- como número decimal
65 - como hexadecimal
0x41 - como caractere ASCII
'A'
Repara na ideia central:
os bits são os mesmos; o significado muda conforme o tipo e o contexto.
Representação de dados: a memória não “vê” semântica
Seção intitulada “Representação de dados: a memória não “vê” semântica”Olha esse bloco de 1 byte:
Bits: 01000001Dec: 65Hex: 0x41ASCII: 'A'A memória não sabe se isso é letra ou número.
Quem decide isso é:
- o tipo
- a instrução usada
- a forma de leitura
É por isso que caracteres têm valor numérico intercambiável.
No ASCII:
'A'=65'B'=66'a'=97'0'=48
Se quiser a tabela completa, veja Tabela ASCII.
Diagrama mental: o mesmo dado, interpretações diferentes
Seção intitulada “Diagrama mental: o mesmo dado, interpretações diferentes”Endereço: 0x1000
+--------+| 01000001 |+--------+
Se lido como unsigned char -> 65Se lido como char ASCII -> 'A'Se lido como binário puro -> 01000001Essa é uma das bases mais importantes da computação.
Números inteiros
Seção intitulada “Números inteiros”Inteiros representam valores sem parte fracionária.
Exemplos clássicos:
- idade
- quantidade
- tentativas
- estoque
- posição
Tamanho dos inteiros nas linguagens principais
Seção intitulada “Tamanho dos inteiros nas linguagens principais”Em C, o tamanho exato depende da plataforma e do compilador, mas existe um mínimo garantido pelo padrão.
char // pelo menos 8 bitsshort // pelo menos 16 bitsint // pelo menos 16 bitslong // pelo menos 32 bitslong long // pelo menos 64 bitsEm C++, a lógica base é parecida com C:
charshortintlonglong longMas C++ te dá casts mais seguros e tipos utilitários em bibliotecas modernas.
JavaScript
Seção intitulada “JavaScript”JavaScript é diferente.
Quase todo número comum é Number, que usa ponto flutuante de 64 bits no padrão IEEE 754.
Ou seja:
- inteiro pequeno funciona bem
- decimal existe
- inteiro muito grande perde precisão
console.log(typeof 10); // "number"console.log(typeof 10.5); // "number"Para inteiros realmente grandes:
const id = 9007199254740993n;console.log(typeof id); // "bigint"Python abstrai mais.
int em Python cresce conforme a necessidade.
x = 10y = 10**100
print(type(x)) # <class 'int'>print(type(y)) # <class 'int'>Isso é ótimo para ergonomia, mas não significa custo zero.
Inteiro gigante consome mais memória e mais processamento.
Inteiros com sinal e sem sinal
Seção intitulada “Inteiros com sinal e sem sinal”Em linguagens como C e C++, isso importa muito.
Permite números negativos e positivos.
Unsigned
Seção intitulada “Unsigned”Só permite zero e positivos.
Exemplo com 8 bits:
unsigned 8 bits: 0 a 255signed 8 bits: -128 a 127Como negativos são armazenados: complemento de dois
Seção intitulada “Como negativos são armazenados: complemento de dois”A forma mais comum de representar inteiros negativos é o complemento de dois.
Exemplo com 8 bits:
5 = 00000101 -5 = 11111011Como gerar -5 em complemento de dois:
5 em binário: 00000101inverte os bits: 11111010soma 1: 11111011Isso importa porque overflow, casting e aritmética binária dependem dessa representação.
Exemplo real em C
Seção intitulada “Exemplo real em C”#include <stdio.h>
int main(void) { signed char a = -5; unsigned char b = 250;
printf("a = %d\n", a); printf("b = %u\n", b); return 0;}Overflow: quando o valor não cabe
Seção intitulada “Overflow: quando o valor não cabe”Um tipo tem limite.
Se você tenta guardar valor além do limite, dá problema.
Exemplo conceitual com unsigned char:
Máximo: 255
255 + 1 = 0 // overflow por wraparound em unsignedExemplo em C:
#include <stdio.h>
int main(void) { unsigned char x = 255; x = x + 1; printf("%u\n", x); // normalmente 0 return 0;}Em signed, overflow pode ser ainda pior, porque comportamento indefinido entra na conversa em C e C++.
Decimal para binário: parte inteira
Seção intitulada “Decimal para binário: parte inteira”Se você quer converter decimal inteiro para binário manualmente, divide por 2 e guarda os restos.
Exemplo com 13:
13 / 2 = 6 resto 1 6 / 2 = 3 resto 0 3 / 2 = 1 resto 1 1 / 2 = 0 resto 1
Lendo de baixo para cima:13 = 1101Decimal fracionário para binário
Seção intitulada “Decimal fracionário para binário”Para frações, multiplica por 2 e observa a parte inteira.
Exemplo com 0.625:
0.625 * 2 = 1.25 -> 10.25 * 2 = 0.5 -> 00.5 * 2 = 1.0 -> 1
0.625 = 0.101 em binárioEntão:
10.625 = 1010.101Números de ponto flutuante
Seção intitulada “Números de ponto flutuante”Agora vem a parte onde muita gente apanha sem perceber.
Ponto flutuante não representa “qualquer decimal exatamente”.
Ele representa aproximações binárias.
Por isso aparecem casos como:
console.log(0.1 + 0.2); // 0.30000000000000004print(0.1 + 0.2) # 0.30000000000000004#include <iostream>
int main() { std::cout << (0.1 + 0.2) << '\n';}Como um float é dividido na memória
Seção intitulada “Como um float é dividido na memória”No padrão IEEE 754, um float de 32 bits costuma ser organizado assim:
31 23 0+-----------+-----------+| sinal | expoente | mantissa |+-----------+-----------+
1 bit 8 bits 23 bitsPara double de 64 bits:
63 52 0+------------+---------------------+| sinal | expoente | mantissa |+------------+---------------------+
1 bit 11 bits 52 bitsIsso explica por que:
- comparação de float pode falhar
- precisão é limitada
- dinheiro em
floaté armadilha
Exemplo de comparação perigosa
Seção intitulada “Exemplo de comparação perigosa”a = 0.1 + 0.2b = 0.3
print(a == b) # FalseMelhor abordagem:
import math
print(math.isclose(0.1 + 0.2, 0.3)) # TrueEm C++:
#include <cmath>#include <iostream>
int main() { double a = 0.1 + 0.2; double b = 0.3; std::cout << std::boolalpha << (std::fabs(a - b) < 1e-9) << '\n';}Dinheiro: use decimal apropriado ou inteiro em menor unidade
Seção intitulada “Dinheiro: use decimal apropriado ou inteiro em menor unidade”Regra prática:
R$ 10,99como1099centavos- ou tipo decimal apropriado na stack escolhida
Exemplo em JavaScript usando centavos:
const priceInCents = 1099;const quantity = 3;
const total = priceInCents * quantity;console.log(total); // 3297console.log((total / 100).toFixed(2)); // "32.97"Exemplo em Python:
price_cents = 1099quantity = 3
total_cents = price_cents * quantityprint(total_cents) # 3297print(total_cents / 100) # 32.97Caracteres: letras também são números
Seção intitulada “Caracteres: letras também são números”Isso aqui é muito importante.
Um caractere não é magia. Ele também é representado numericamente.
No ASCII:
'A'=65'B'=66'Z'=90'a'=97'0'=48
Exemplo visual:
'A'Decimal: 65Hex: 0x41Bin: 01000001Você falou “A = 52”, mas o valor correto em ASCII é 65.
52 em ASCII é o caractere '4'.
Código: caractere para número e número para caractere
Seção intitulada “Código: caractere para número e número para caractere”#include <stdio.h>
int main(void) { char c = 'A'; printf("%c\n", c); // A printf("%d\n", c); // 65 return 0;}#include <iostream>
int main() { char c = 'A'; std::cout << c << '\n'; std::cout << static_cast<int>(c) << '\n';}JavaScript
Seção intitulada “JavaScript”const c = 'A';
console.log(c.charCodeAt(0)); // 65console.log(String.fromCharCode(65)); // Aprint(ord('A')) # 65print(chr(65)) # AASCII versus Unicode
Seção intitulada “ASCII versus Unicode”ASCII cobre 128 códigos clássicos.
Ótimo para entender base.
Mas software moderno geralmente precisa de Unicode, porque:
- acentos existem
- emojis existem
- alfabetos de vários idiomas existem
ASCII é ponto de partida.
Unicode é o mundo real.
Mesmo assim, entender ASCII continua extremamente valioso, porque ajuda você a entender:
- comparação entre caracteres
- ordenação básica
- parsing
- manipulação de bytes
- serialização de texto
Strings: texto não é só um monte de letras
Seção intitulada “Strings: texto não é só um monte de letras”String é sequência de caracteres.
Mas a implementação muda bastante por linguagem.
Em C, string é array de char terminado por byte nulo '\0'.
#include <stdio.h>
int main(void) { char name[] = "Edu";
printf("%c\n", name[0]); // E printf("%c\n", name[1]); // d printf("%c\n", name[2]); // u printf("%d\n", name[3]); // 0 -> '\0' return 0;}Diagrama:
name = "Edu"
+-----+-----+-----+------+| 'E' | 'd' | 'u' | '\0' |+-----+-----+-----+------+Em C++, você pode ter char[], const char* ou std::string.
#include <iostream>#include <string>
int main() { std::string name = "Edu"; std::cout << name.size() << '\n'; // 3}JavaScript
Seção intitulada “JavaScript”Strings em JavaScript são imutáveis.
const name = "Edu";
console.log(name[0]); // Econsole.log(name.length); // 3Strings em Python também são imutáveis.
name = "Edu"
print(name[0]) # Eprint(len(name)) # 3Booleanos
Seção intitulada “Booleanos”Booleano modela estado binário.
true / false1 / 0ligado / desligadoativo / inativoEm C:
#include <stdbool.h>#include <stdio.h>
int main(void) { bool active = true; printf("%d\n", active); // 1 return 0;}Em JavaScript:
const active = true;console.log(typeof active); // booleanEm Python:
active = Trueprint(type(active)) # <class 'bool'>Null, None, undefined e companhia
Seção intitulada “Null, None, undefined e companhia”Aqui mora muita confusão.
C puro trabalha muito com ponteiros nulos:
int *ptr = NULL;C++ moderno usa nullptr:
int* ptr = nullptr;JavaScript
Seção intitulada “JavaScript”JavaScript tem null e undefined.
let a = null;let b;
console.log(a); // nullconsole.log(b); // undefinedPython usa None.
value = NoneRegra mental:
- ausência de valor não é a mesma coisa que zero
- ausência de valor não é string vazia
- ausência de valor não é
false
Casting e conversão
Seção intitulada “Casting e conversão”Agora chegamos numa parte crítica.
Casting é conversão de um tipo para outro.
Ela pode ser:
- implícita
- explícita
- segura
- perigosa
Casting implícito
Seção intitulada “Casting implícito”A linguagem converte sem você pedir.
Às vezes ajuda.
Às vezes planta bomba.
Exemplo em C
Seção intitulada “Exemplo em C”int a = 10;double b = a; // conversão implícita de int para doubleExemplo em JavaScript
Seção intitulada “Exemplo em JavaScript”console.log("5" + 1); // "51"console.log("5" - 1); // 4Isso acontece porque JavaScript faz coerção implícita de tipos.
É poderoso.
Mas também é uma fábrica de bug quando usado sem atenção.
Casting explícito
Seção intitulada “Casting explícito”Você deixa claro que quer converter.
#include <stdio.h>
int main(void) { double x = 3.99; int y = (int)x; printf("%d\n", y); // 3 return 0;}Prefira static_cast em vez de cast estilo C quando possível:
#include <iostream>
int main() { double x = 3.99; int y = static_cast<int>(x); std::cout << y << '\n'; // 3}JavaScript
Seção intitulada “JavaScript”console.log(Number("42")); // 42console.log(parseInt("42", 10)); // 42console.log(parseFloat("3.14")); // 3.14print(int("42")) # 42print(float("3.14")) # 3.14print(str(42)) # "42"Conversões perigosas
Seção intitulada “Conversões perigosas”Perda de parte decimal
Seção intitulada “Perda de parte decimal”double price = 19.99;int truncated = static_cast<int>(price); // 19Overflow por narrowing
Seção intitulada “Overflow por narrowing”#include <stdio.h>
int main(void) { int x = 300; unsigned char y = (unsigned char)x; printf("%u\n", y); // pode virar 44 return 0;}Porque:
300 % 256 = 44String inválida para número
Seção intitulada “String inválida para número”value = "abc"# int(value) -> ValueErrorconsole.log(Number("abc")); // NaNNaN: número que não é número
Seção intitulada “NaN: número que não é número”Em JavaScript:
const value = Number("abc");
console.log(value); // NaNconsole.log(Number.isNaN(value)); // trueEsse tipo de caso precisa ser tratado antes de seguir lógica de negócio.
Hexadecimal e leitura de memória
Seção intitulada “Hexadecimal e leitura de memória”Hexadecimal aparece o tempo todo porque ele conversa muito bem com bytes.
Cada dígito hexadecimal representa 4 bits.
Binário: 11111111Hexadecimal: FFDecimal: 255Conversão:
1111 1111 F FOutro exemplo:
0100 0001 4 1
0x41 = 65 = 'A'Endianness: ordem dos bytes
Seção intitulada “Endianness: ordem dos bytes”Quando um valor ocupa mais de 1 byte, a ordem de armazenamento importa.
Exemplo com 0x12345678:
Big-endian
Seção intitulada “Big-endian”+------+------+------+------+| 12 | 34 | 56 | 78 |+------+------+------+------+Little-endian
Seção intitulada “Little-endian”+------+------+------+------+| 78 | 56 | 34 | 12 |+------+------+------+------+Isso aparece em:
- serialização
- redes
- leitura de arquivos binários
- interoperabilidade entre sistemas
Tamanho de tipos em prática
Seção intitulada “Tamanho de tipos em prática”Exemplo em C:
#include <stdio.h>
int main(void) { printf("char: %zu\n", sizeof(char)); printf("short: %zu\n", sizeof(short)); printf("int: %zu\n", sizeof(int)); printf("long: %zu\n", sizeof(long)); printf("long long: %zu\n", sizeof(long long)); printf("float: %zu\n", sizeof(float)); printf("double: %zu\n", sizeof(double)); return 0;}Exemplo em C++:
#include <iostream>
int main() { std::cout << sizeof(char) << '\n'; std::cout << sizeof(int) << '\n'; std::cout << sizeof(double) << '\n';}Como modelar dados de verdade
Seção intitulada “Como modelar dados de verdade”Antes de escolher tipo, responde:
- Isso é quantidade, identidade, texto, estado, data ou dinheiro?
- Eu vou calcular com isso?
- Existe limite conhecido?
- Preciso preservar exatidão?
- Pode faltar valor?
- Esse dado vem de usuário, API ou arquivo?
Essas perguntas evitam muita gambiarra.
Exemplos de modelagem correta
Seção intitulada “Exemplos de modelagem correta”Usuário
Seção intitulada “Usuário”nome -> stringidade -> inteiroativo -> booleanocriadoEm -> data/horaidPedido -> string ou inteiro de domíniovalorCentavos -> inteiropago -> booleanostatus -> enum ou string validadaProduto
Seção intitulada “Produto”sku -> stringestoque -> inteiroprecoCentavos -> inteiroMini laboratório de exemplos
Seção intitulada “Mini laboratório de exemplos”C: caractere e inteiro compartilham base numérica
Seção intitulada “C: caractere e inteiro compartilham base numérica”#include <stdio.h>
int main(void) { char c = 'A'; int code = c;
printf("char: %c\n", c); printf("code: %d\n", code); return 0;}C++: truncamento explícito
Seção intitulada “C++: truncamento explícito”#include <iostream>
int main() { double ratio = 9.87; int whole = static_cast<int>(ratio);
std::cout << ratio << '\n'; std::cout << whole << '\n';}JavaScript: coerção traiçoeira
Seção intitulada “JavaScript: coerção traiçoeira”console.log("10" + 2); // "102"console.log("10" - 2); // 8console.log(true + 1); // 2console.log(false + 1); // 1Python: conversão segura com tratamento
Seção intitulada “Python: conversão segura com tratamento”raw = "42"
try: value = int(raw) print(value + 8)except ValueError: print("entrada inválida")Erros clássicos de iniciante
Seção intitulada “Erros clássicos de iniciante”- usar string para tudo
- comparar
"10"com10 - usar
floatpara dinheiro - achar que
charnão tem valor numérico - converter sem validar
- misturar ausência de valor com zero
- ignorar limite do tipo
Sinais de que a modelagem está ruim
Seção intitulada “Sinais de que a modelagem está ruim”- o mesmo campo muda de tipo em camadas diferentes
- você converte toda hora
- o sistema está cheio de
ifdefensivo sem clareza - bugs aparecem em ordenação, filtro, cálculo e serialização
Exercícios que realmente valem
Seção intitulada “Exercícios que realmente valem”- Converta
13para binário manualmente. - Converta
0.625para binário manualmente. - Mostre em código que
'A'vale65. - Modele um pedido usando centavos em vez de float.
- Faça parsing seguro de string para inteiro em C, C++, JavaScript e Python.
- Compare
0.1 + 0.2com0.3e explique o resultado.
Checklist forte de tipos de dados
Seção intitulada “Checklist forte de tipos de dados”- Você entende bit, byte e representação binária?
- Você sabe a diferença entre inteiro, float, char, string e bool?
- Você sabe que caractere também é número?
- Você conhece o básico de complemento de dois?
- Você entende por que float falha em dinheiro?
- Você sabe quando usar cast explícito?
- Você trata input inválido antes de converter?
Se você fecha esses pontos, sua base já sai do nível “tutorial” e entra no nível de engenharia.
Próximas ações
Seção intitulada “Próximas ações”- Consulte agora a Tabela ASCII
- Depois avance para Estruturas de Dados
- Se quiser consolidar raciocínio, siga para Lógica de Programação