C++ Tipos de Dados

Toda variável em C++ tem um tipo, escolhido quando ela é criada: int idade, double altura. O tipo diz que espécie de valor cabe na caixa, quanto espaço ela ocupa na memória e o que dá para fazer com ela (somar, juntar textos, perguntar se é verdade). Esta aula é o mapa: mostra os tipos que você vai usar o tempo todo, o tamanho real de cada um e como escolher. Cada família tem depois a sua própria aula.

Você vai aprender
  • Os tipos do dia a dia: int, double, char, bool e std::string.
  • Os "parentes": short, long, long long, float, long double.
  • Como medir o tamanho de um tipo com sizeof, e os tamanhos reais no Linux da Ana.
  • Como escolher o tipo certo para cada informação.
  • A diferença entre tipos fundamentais (da linguagem) e tipos da biblioteca (como std::string).

Todos os programas desta aula foram compilados com o g++ 15.2 na máquina fictícia da Ana (usuária ana, computador notebook, um PC comum de 64 bits), na pasta ~/cpp, com o comando padrão do guia: g++ -std=c++23 -Wall -Wextra arquivo.cpp -o programa.


A ideia: cada coisa no seu recipiente

Na cozinha, cada coisa tem o seu recipiente: ovos vão na caixa de ovos, leite vai na garrafa, açúcar vai no pote. Você até consegue pôr leite na caixa de ovos, mas vai dar errado. E ninguém guarda uma colher de sal num balde.

Os tipos do C++ são esses recipientes. Escolher o tipo é responder três perguntas:

  1. Que espécie de informação? Número inteiro, número com vírgula, uma letra, sim/não, um texto.
  2. De que tamanho? A idade de uma pessoa cabe num recipiente pequeno; a população do mundo precisa de um grande.
  3. Com que precisão? Um preço precisa de centavos; o número de alunos, não.

1. Os cinco tipos do dia a dia

#include <iostream>
#include <string>

int main() {
    int idade = 29;
    double altura = 1.65;
    char inicial = 'A';
    bool clienteVip = true;
    std::string nome = "Ana";
    std::cout << "Idade: " << idade << "\n";
    std::cout << "Altura: " << altura << "\n";
    std::cout << "Inicial: " << inicial << "\n";
    std::cout << "VIP: " << clienteVip << "\n";
    std::cout << "Nome: " << nome << "\n";
}
$ g++ -std=c++23 -Wall -Wextra tipos.cpp -o tipos
$ ./tipos
Idade: 29
Altura: 1.65
Inicial: A
VIP: 1                   « true aparece como 1 (a aula bool explica)
Nome: Ana
TipoNome vem deGuardaComo se escreve o valorAula
intinteger, "inteiro"Números inteiros, positivos ou negativos29, -7, 0Inteiros
doubledouble precision, "precisão dupla"Números com vírgula (fração)1.65, -0.5, 3.0 (com ponto)float e double
charcharacter, "caractere"Um caractere'A', '7', '?' (aspas simples)Caracteres
boolGeorge Boole, matemáticoVerdadeiro ou falsotrue, falseBooleanos
std::string"cadeia" (de caracteres)Texto de qualquer tamanho"Ana", "" (aspas duplas)Strings

Com esses cinco você escreve quase todos os programas do Nível 1. Os outros tipos são variações de tamanho e de precisão dos mesmos números.

Experimente: mude os valores para os seus dados e rode. Depois tente pôr "Ana" (com aspas duplas) no char inicial e leia o erro: um char guarda um caractere, entre aspas simples.

#include <iostream>
#include <string>

int main() {
    std::string nome = "Ana";
    int idade = 29;
    double altura = 1.65;
    char inicial = 'A';
    bool gostaDeCafe = true;
    std::cout << nome << ", " << idade << " anos, " << altura << " m, inicial "
              << inicial << ", gosta de café: " << gostaDeCafe << "\n";
}

2. Medir o tamanho: sizeof

A memória do computador é medida em bytes. Um byte é um pedacinho de memória com 8 bits (cada bit é um 0 ou 1) e consegue guardar 256 valores diferentes. Quanto mais bytes um tipo tem, maiores (ou mais precisos) os números que ele guarda.

O operador sizeof ("tamanho de") responde quantos bytes um tipo ocupa:

#include <iostream>
#include <string>

int main() {
    std::cout << "bool:        " << sizeof(bool) << "\n";
    std::cout << "char:        " << sizeof(char) << "\n";
    std::cout << "short:       " << sizeof(short) << "\n";
    std::cout << "int:         " << sizeof(int) << "\n";
    std::cout << "long:        " << sizeof(long) << "\n";
    std::cout << "long long:   " << sizeof(long long) << "\n";
    std::cout << "float:       " << sizeof(float) << "\n";
    std::cout << "double:      " << sizeof(double) << "\n";
    std::cout << "long double: " << sizeof(long double) << "\n";
    std::cout << "std::string: " << sizeof(std::string) << "\n";
}
$ g++ -std=c++23 -Wall -Wextra tamanhos.cpp -o tamanhos
$ ./tamanhos
bool:        1
char:        1
short:       2
int:         4
long:        8
long long:   8
float:       4
double:      8
long double: 16
std::string: 32

Os espaços depois dos nomes ("int: ") estão lá só para alinhar a saída em colunas.

A tabela completa

TipoBytes no Linux 64 bits (g++ 15)GuardaFaixa aproximada
bool1verdadeiro/falsotrue ou false
char1um caractere (um número pequeno por dentro)-128 a 127
short2inteiro pequeno-32 768 a 32 767
int4inteiro (o padrão)cerca de ±2,1 bilhões
long8inteiro grandecerca de ±9,2 quintilhões
long long8inteiro grande (8 bytes garantidos)cerca de ±9,2 quintilhões
float4número com vírgula, precisão simplesuns 6 a 7 dígitos certos
double8número com vírgula, precisão dupla (o padrão)uns 15 a 16 dígitos certos
long double16número com vírgula, mais precisãouns 18 dígitos certos
std::string32texto(qualquer tamanho; veja abaixo)

Os limites exatos de cada inteiro, com std::numeric_limits, estão em Inteiros; a precisão dos números com vírgula, em float e double. A referência de tipos junta tudo numa página de consulta.

Os tamanhos não são iguais em todo computador

A norma do C++ só garante mínimos: int tem pelo menos 2 bytes, long pelo menos 4, long long pelo menos 8. Os números acima valem para o Linux 64 bits da Ana. No Windows, por exemplo, long tem 4 bytes. No editor do guia, que roda num computador "de 32 bits" simulado (WebAssembly), long também tem 4 bytes (conferido com o Clang para esse alvo), e std::string dá outro número, porque o editor usa outra biblioteca padrão. Quando o tamanho exato importa, use long long ou os tipos de tamanho fixo, como std::int64_t (aula Inteiros).

sizeof de uma variável, e o mistério do std::string

sizeof também mede uma variável. Com variável, os parênteses são opcionais:

#include <iostream>
#include <string>

int main() {
    int idade = 29;
    std::string curto = "Ana";
    std::string longo = "Ana Clara de Souza Albuquerque, moradora de Recife";
    std::cout << sizeof(idade) << " " << sizeof idade << "\n";
    std::cout << sizeof(curto) << " " << sizeof(longo) << "\n";
    std::cout << curto.size() << " " << longo.size() << "\n";
}
$ g++ -std=c++23 -Wall -Wextra sizeofvar.cpp -o sizeofvar
$ ./sizeofvar
4 4
32 32                    « o mesmo tamanho para 3 e para 50 letras?
3 50                     « .size() conta as letras de verdade

Como um texto de 50 letras cabe em 32 bytes? Não cabe. O std::string é como uma ficha de biblioteca: a ficha tem sempre o mesmo tamanho (32 bytes) e diz onde está o livro. Textos curtos cabem na própria ficha; textos longos ficam guardados em outra parte da memória, e a ficha só aponta para lá. O sizeof mede a ficha; para saber quantas letras o texto tem, use .size() (aula Funções de String).

Os valores escritos também têm tipo

Um número escrito direto no código (um literal) também tem tipo. O C++ decide pelo jeito de escrever:

$ cat literais.cpp
#include <iostream>

int main() {
    std::cout << sizeof(42) << " " << sizeof(4.5) << " " << sizeof(4.5f) << " "
              << sizeof('A') << " " << sizeof(true) << "\n";
}
$ g++ -std=c++23 -Wall -Wextra literais.cpp -o literais
$ ./literais
4 8 4 1 1
LiteralTipoPor quê
42intNúmero sem ponto.
4.5doubleNúmero com ponto.
4.5ffloatO f no fim pede float.
'A'charAspas simples.
trueboolPalavra-chave de verdadeiro.
"Ana"texto "cru" do C (não é std::string!)A aula auto mostra o tipo exato e o sufixo s que o transforma em std::string.

3. Escolher o tipo certo

Na dúvida, a pergunta é "o que eu quero guardar?". Esta tabela resolve quase todos os casos:

Quero guardar…UseExemplo
Uma contagem, uma idade, uma quantidade, uma nota de 0 a 10 sem fraçãointint alunos = 32;
Um número que pode passar de 2 bilhões (população, bytes de um arquivo, milissegundos)long longlong long habitantes = 8'100'000'000;
Uma medida com fração (altura, peso, média, temperatura)doubledouble media = 7.75;
Um preçodouble no começo; em sistemas de dinheiro de verdade, centavos em long longlong long precoCentavos = 1250;
Uma única letra ou símbolo (uma opção de menu, uma tecla)charchar opcao = 's';
Sim ou não, ligado ou desligadoboolbool pago = false;
Um nome, uma frase, qualquer textostd::stringstd::string cidade = "Recife";
Um número de telefone, CEP ou CPFstd::string (!)std::string cep = "01310-100";
Telefone não é número

Você nunca vai somar dois telefones. E números assim têm zeros à esquerda (01310), traços e parênteses que um int jogaria fora. Regra: se você não faz contas com aquilo, guarde como texto.

O que acontece com o tipo errado

O tipo errado raramente dá erro de compilação. Na maioria das vezes, o programa roda e dá a resposta errada:

#include <iostream>

int main() {
    int preco = 4.99;
    int pesoKg = 2.5;
    double total = preco * pesoKg;
    std::cout << "Total: " << total << "\n";
}
$ g++ -std=c++23 -Wall -Wextra errado.cpp -o errado
$ ./errado
Total: 8                 « 4 × 2: os centavos e o meio quilo sumiram

O int jogou fora a parte depois do ponto (4.99 virou 4; 2.5 virou 2), e o g++ não avisou com -Wall -Wextra. A aula Variáveis mostra como a inicialização com chaves (int preco{4.99};) transforma esse silêncio em erro.

Missão: conserte os tipos (só os tipos, sem mudar os números) para o total da feira da Ana sair certo: Total: 12.475. (No editor, o Clang ainda mostra avisos sobre a conversão: leia-os, eles apontam exatamente as linhas a consertar.)

#include <iostream>

int main() {
    int preco = 4.99;
    int pesoKg = 2.5;
    double total = preco * pesoKg;
    std::cout << "Total: " << total << "\n";
}
#include <iostream>

int main() {
    double preco = 4.99;
    double pesoKg = 2.5;
    double total = preco * pesoKg;
    std::cout << "Total: " << total << "\n";
}

4. Tipos fundamentais × tipos da biblioteca

Você deve ter reparado que quatro tipos são escritos "pelados" (int, double, char, bool) e um tem std:: na frente e pede um #include (std::string). Não é por acaso.

Tipos fundamentaisTipos da biblioteca padrão
Exemplosint, double, char, bool, float, long long, voidstd::string, std::vector, std::array, std::map
De onde vêmFazem parte da linguagem: são palavras-chaveForam escritos em C++ por quem fez a biblioteca, usando os fundamentais
Precisam de #include?NãoSim: <string>, <vector>…
PrefixoNenhumstd:: ("standard", padrão; veja Namespaces)
ComparaçãoOs tijolosParedes prontas, feitas com os tijolos

O void ("vazio") é o tipo fundamental que quer dizer "nenhum valor"; ele aparece nas funções que não devolvem nada. E a partir do Nível 2 você vai criar os seus próprios tipos, com structs e classes, do mesmo jeito que a biblioteca criou o std::string.

Esquecer o std::

#include <iostream>
#include <string>

int main() {
    string nome = "Ana";
    std::cout << nome << "\n";
}
$ g++ -std=c++23 -Wall -Wextra semstd.cpp -o semstd
semstd.cpp: In function ‘int main()’:
semstd.cpp:5:5: error: ‘string’ was not declared in this scope
    5 |     string nome = "Ana";
      |     ^~~~~~
semstd.cpp:5:5: note: suggested alternatives:
In file included from /usr/include/c++/15/iosfwd:43,
                 from /usr/include/c++/15/ios:42,
                 from /usr/include/c++/15/bits/ostream.h:43,
                 from /usr/include/c++/15/ostream:42,
                 from /usr/include/c++/15/iostream:43,
                 from semstd.cpp:1:
/usr/include/c++/15/bits/stringfwd.h:79:33: note:   ‘std::string’
   79 |   typedef basic_string<char>    string;
      |                                 ^~~~~~
In file included from /usr/include/c++/15/ostream:44:
/usr/include/c++/15/format:5121:5: note:   ‘std::range_format::string’
 5121 |     string,
      |     ^~~~~~
In file included from /usr/include/c++/15/bits/locale_classes.h:42,
                 from /usr/include/c++/15/bits/ios_base.h:43,
                 from /usr/include/c++/15/ios:46:
/usr/include/c++/15/string:80:11: note:   ‘std::pmr::string’
   80 |     using string    = basic_string<char>;
      |           ^~~~~~
semstd.cpp:6:18: error: ‘nome’ was not declared in this scope
    6 |     std::cout << nome << "\n";
      |                  ^~~~

A mensagem é longa, mas só duas linhas importam:

  • error: ‘string’ was not declared in this scope: sem o std::, o compilador não acha o nome string.
  • note: ‘std::string’: entre as "alternativas sugeridas" (suggested alternatives), a primeira é a certa. As linhas In file included from… só mostram onde, dentro da biblioteca, ele encontrou cada sugestão; pode pular.
  • O segundo erro (‘nome’ was not declared) é consequência do primeiro: como a declaração falhou, nome não existe. Conserte o primeiro erro e ele some.
E se eu esquecer o #include <string>?

No laboratório, um programa com std::string e só #include <iostream> compilou e rodou, no g++ e no Clang, porque o <iostream> da biblioteca de hoje já traz o <string> junto, "de carona". Mas a norma não garante essa carona, e outra versão do compilador pode recusar o mesmo arquivo. Regra do guia: usou, inclua.


Quando dá errado

O programa compila, mas o número perde a parte depois do ponto

O que significa: um valor com vírgula foi parar numa variável inteira (int, long…), e a fração foi jogada fora.

Como consertar: use double para medidas e preços. Inicialize com chaves ({ }) para o compilador barrar esse corte.

error: ‘string’ was not declared in this scope

O que significa: faltou o std:: (ou o #include <string>).

Como consertar: escreva std::string e confira o #include <string> no topo.

error: invalid conversion from ‘const char*’ to ‘char’ (ou to ‘int’)

O que significa: um texto entre aspas duplas foi posto numa variável que não é de texto.

Como consertar: para texto, std::string. Para um único caractere, char com aspas simples: 'A'. A diferença é explicada em Caracteres.

O sizeof deu um número diferente do da tabela

O que significa: você está em outro sistema (Windows, 32 bits, o editor do guia em WebAssembly). Os tamanhos dependem da plataforma.

Como consertar: nada a consertar. Se o seu programa depende de um tamanho exato, use long long ou os tipos de <cstdint>, como std::int32_t (aula Inteiros).


Referência rápida

EscritaO que faz
int x = 29;Inteiro
long long x = 8'100'000'000;Inteiro grande (8 bytes)
double x = 1.65;Número com vírgula (o padrão)
float x = 1.65f;Número com vírgula, menos preciso
char c = 'A';Um caractere (aspas simples)
bool b = true;Verdadeiro ou falso
std::string s = "Ana";Texto (precisa de #include <string>)
sizeof(tipo) / sizeof variavelQuantos bytes ocupa
texto.size()Quantos caracteres um std::string tem

Exercícios

1. O tipo da média

A média de um aluno pode ser 7.75. Complete com o tipo certo:

media = 7.75;

2. Quantos bytes?

No Linux 64 bits da Ana, sizeof(int) mostra:

3. Qual é o melhor tipo para guardar um CEP como 01310-100?

4. Um std::string com 3 letras e outro com 50 letras. O que sizeof mostra para cada um (g++ 15, Linux 64 bits)?

5. Qual destes é um tipo da biblioteca, e não da linguagem?

Missão final: a ficha do cliente

Missão: crie cinco variáveis, cada uma com o tipo certo: o nome Bruno, a idade 31, a altura 1.78, a inicial B e se ele é estudante (não é: false). Mostre a ficha exatamente assim (o false aparece como 0):

Nome: Bruno
Idade: 31
Altura: 1.78
Inicial: B
Estudante: 0
#include <iostream>
#include <string>

int main() {
    // crie as cinco variáveis aqui

    // mostre a ficha aqui
}
#include <iostream>
#include <string>

int main() {
    std::string nome = "Bruno";
    int idade = 31;
    double altura = 1.78;
    char inicial = 'B';
    bool estudante = false;
    std::cout << "Nome: " << nome << "\n";
    std::cout << "Idade: " << idade << "\n";
    std::cout << "Altura: " << altura << "\n";
    std::cout << "Inicial: " << inicial << "\n";
    std::cout << "Estudante: " << estudante << "\n";
}

Resumo

  • O tipo diz que valor cabe na variável, quanto espaço ela ocupa e o que dá para fazer com ela.
  • Os cinco do dia a dia: int (inteiro), double (com vírgula), char (um caractere, 'A'), bool (true/false) e std::string (texto, "Ana").
  • sizeof mede bytes. No Linux 64 bits: bool/char 1, short 2, int/float 4, long/long long/double 8, long double 16, std::string 32. Outros sistemas podem diferir.
  • Escolha pelo que você guarda: contagem → int; medida → double; sim/não → bool; texto (inclusive telefone e CEP) → std::string.
  • Tipo errado quase sempre compila e dá resposta errada.
  • Fundamentais (int, double…) são da linguagem; os da biblioteca (std::string, std::vector) pedem #include e std::.