C++: Fundamentos de Ponteiros

Última atualização: 2026-08-26

Nas aulas anteriores, variáveis são armazenadas em algum lugar da memória.

Mas onde exatamente fica esse "lugar"? Você pode acessá-lo diretamente?

Ponteiros são variáveis que armazenam endereços — eles permitem manipular a memória diretamente.



1. O que é um Ponteiro?

(1) 1.1 Ponteiros no Dia a Dia

Analogia da Vida Real Equivalente em Programa
O endereço da sua casa (ex: "Rua Principal, 123...") Ponteiro (armazena um endereço)
Sua casa real (o prédio para o qual o endereço aponta) Variável (o espaço de memória para o qual o endereço aponta)

Essência de um ponteiro: Uma variável que armazena um endereço.

(2) 1.2 Por Que Precisamos de Ponteiros?

  1. Alocação dinâmica de memória (coberto mais tarde com new / delete)
  2. Funções precisam modificar variáveis externas (passar ponteiros para funções)
  3. Trabalhar com arrays (nomes de arrays são ponteiros)
  4. Implementar estruturas de dados complexas (listas encadeadas, árvores, grafos)


2. Declaração e Inicialização de Ponteiros

(1) 2.1 Declarando um Ponteiro

Sintaxe:

▶ Exemplo 2: Exemplo de Código (Dificuldade ⭐)

TEXT 📖 Somente leitura
Type* nomePonteiro;

Saída:

TEXT 📖 Somente leitura
(Saída do programa)

Exemplo:

CPP
#include <iostream>

int main() {
 int* pInt; // ponteiro para int
 double* pDouble; // ponteiro para double
 char* pChar; // ponteiro para char
 
 return 0;
}

💡 Ponto-chave: Type* significa "um ponteiro para esse tipo."


(2) 2.2 Operador de Endereço (&)

& é usado para obter o endereço de uma variável.

CPP
#include <iostream>

int main() {
 int x = 5;
 
 std::cout << "Valor de x: " << x << std::endl;
 std::cout << "Endereço de x: " << &x << std::endl; // Saída semelhante a 0x7ffd4a3b
 
 return 0;
}

Saída (exemplo):

TEXT 📖 Somente leitura
Valor de x: 5
Endereço de x: 0x7ffd4a3b

💡 Dica: O formato específico dos endereços depende do sistema e do compilador.


(3) 2.3 Inicializando um Ponteiro

CPP
#include <iostream>

int main() {
 int x = 5;
 int* p = &x; // p aponta para x(p armazena o endereço de x)
 
 std::cout << "Endereço de x: " << &x << std::endl;
 std::cout << "Valor de p: " << p << std::endl; // mesmo que &x
 
 return 0;
}


3. Desreferência

(1) 3.1 Operador de Desreferência (*)

* é usado para acessar o valor que um ponteiro aponta.

CPP
#include <iostream>

int main() {
 int x = 5;
 int* p = &x; // p aponta para x
 
 std::cout << "x = " << x << std::endl; // 5
 std::cout << "*p = " << *p << std::endl; // 5(Desreferência)
 
 return 0;
}

💡 Ponto-chave: *p é essencialmente x!


(2) 3.2 Modificando uma Variável Através de um Ponteiro

CPP
#include <iostream>

int main() {
 int x = 5;
 int* p = &x;
 
 std::cout << "Antes: x = " << x << std::endl; // 5
 
 *p = 100; // Modifica o valor de x via ponteiro
 
 std::cout << "Depois: x = " << x << std::endl; // 100
 
 return 0;
}


4. Tamanho dos Ponteiros

(1) 4.1 sizeof de um Ponteiro

CPP
#include <iostream>

int main() {
 int* pInt;
 double* pDouble;
 char* pChar;
 
 std::cout << "Tamanho de int*: " << sizeof(pInt) << " bytes" << std::endl;
 std::cout << "Tamanho de double*: " << sizeof(pDouble) << " bytes" << std::endl;
 std::cout << "Tamanho de char*: " << sizeof(pChar) << " bytes" << std::endl;
 
 return 0;
}

Saída (sistema de 64 bits):

TEXT 📖 Somente leitura
Tamanho de int*: 8 bytes
Tamanho de double*: 8 bytes
Tamanho de char*: 8 bytes

💡 Ponto-chave: Todos os ponteiros têm o mesmo tamanho (8 bytes em sistemas de 64 bits, 4 bytes em sistemas de 32 bits) — porque todos armazenam endereços.



5. Ponteiros Nulos (nullptr)

(1) 5.1 O que é um Ponteiro Nulo?

Um ponteiro nulo é um ponteiro que não aponta para nenhum objeto.

CPP
#include <iostream>

int main() {
 int* p = nullptr; // Ponteiro nulo (recomendado desde C++11)
 
 if (p == nullptr) {
 std::cout << "p é um ponteiro nulo" << std::endl;
 }
 
 return 0;
}

💡 Dica: Antes do C++11, usava-se NULL (que é essencialmente 0), mas nullptr agora é recomendado.


(2) 5.2 Desreferenciar um Ponteiro Nulo Causa Falha

TEXT 📖 Somente leitura
#include <iostream>

int main() {
 int* p = nullptr;
 std::cout << *p << std::endl; // ❌ Comportamento indefinido! Pode causar falha
 return 0;
}

Resultado da execução:

CPP
Segmentation fault (core dumped) // Linux

Ou

TEXT 📖 Somente leitura
Process finished with exit code -1073741819 // Windows

⚠️ Nunca desreferencie um ponteiro nulo!



6. Ponteiros como Parâmetros de Função

(1) 6.1 O Problema: Funções Precisam Modificar Variáveis Externas

CPP
#include <iostream>

void modifyValue(int x) {
 x = 100; // ❌ modificando uma cópia, não afeta a variável original
}

int main() {
 int a = 5;
 modifyValue(a);
 std::cout << "a = " << a << std::endl; // 5(Inalterado)
 return 0;
}

(2) 6.2 Solução: Passar um Ponteiro

CPP
#include <iostream>

void modifyValue(int* p) {
 *p = 100; // ✅ modifica a variável original via ponteiro
}

int main() {
 int a = 5;
 modifyValue(&a); // Passa o endereço
 std::cout << "a = " << a << std::endl; // 100(Alterado!)
 return 0;
}


7. Prática: Trocando Duas Variáveis

▶ Exemplo 1: Implementando swap com Ponteiros (Dificuldade ⭐)

CPP
#include <iostream>

void swap(int* a, int* b) {
 int temp = *a;
 *a = *b;
 *b = temp;
}

int main() {
 int x = 3, y = 5;
 std::cout << "Antes da troca: x = " << x << ", y = " << y << std::endl;
 
 swap(&x, &y); // Passa o endereço
 
 std::cout << "Depois da troca: x = " << x << ", y = " << y << std::endl;
 
 return 0;
}
▶ Experimente

Saída:

TEXT 📖 Somente leitura
Antes da troca: x = 3, y = 5
Depois da troca: x = 5, y = 3

💡 Dica: Depois você aprenderá referências — implementar swap com referências é ainda mais simples.



8. Erros Comuns

(1) 8.1 Desreferenciar um Ponteiro Não Inicializado

TEXT 📖 Somente leitura
#include <iostream>

int main() {
 int* p; // ❌ Não inicializado (ponteiro selvagem)
 std::cout << *p << std::endl; // ❌ Comportamento indefinido!
 return 0;
}

Correção: Inicialize com nullptr, ou aponte para uma variável existente.


(2) 8.2 Incompatibilidade de Tipo de Ponteiro

CPP
#include <iostream>

int main() {
 int x = 5;
 double* p = &x; // ❌ Erro: int* não pode apontar para int
 return 0;
}

Mensagem de erro do compilador:

TEXT 📖 Somente leitura
error: cannot convert 'int*' to 'double*' in initialization

▶ Exemplo 3: Ponteiros e Arrays (Dificuldade ⭐)

CPP
#include <iostream>

int main() {
    int arr[] = {10, 20, 30, 40, 50};
    int* p = arr; // nome do array é o endereço do primeiro elemento

    for (int i = 0; i < 5; i++) {
        std::cout << "arr[" << i << "] = " << *(p + i) << std::endl;
    }

    return 0;
}
▶ Experimente

Saída:

TEXT 📖 Somente leitura
arr[0] = 10
arr[1] = 20
arr[2] = 30
arr[3] = 40
arr[4] = 50
💡 Dica: O nome do array arr é o endereço do primeiro elemento, equivalente a &arr[0]. Ao percorrer um array com um ponteiro, *(p + i) é equivalente a p[i] ou arr[i].


❓ Perguntas Frequentes

P: Qual a diferença entre ponteiros e referências? R: Será abordado em detalhes mais tarde, mas resumidamente: > - Ponteiros podem apontar para nullptr; referências devem ser inicializadas > - Ponteiros podem ser reassinalados para apontar para outras variáveis; referências não podem ser religadas uma vez vinculadas > - Ponteiros precisam de *p para desreferenciar; referências usam o nome da variável diretamente

Recomendação: Prefira referências, a menos que você precise representar "nada" (então use um ponteiro).

P: Por que todos os ponteiros têm o mesmo tamanho? R: Porque ponteiros todos armazenam endereços — o comprimento de um endereço depende do sistema (4 bytes em 32 bits, 8 bytes em 64 bits). P: Qual a diferença entre um ponteiro nulo e um ponteiro selvagem? R:> - Ponteiro nulo: aponta explicitamente para nullptr (seguro) > - Ponteiro selvagem: aponta para um endereço aleatório, ou para memória liberada (perigoso!)

CPP
int* p1 = nullptr; // Ponteiro nulo (seguro)
int* p2; // ❌ Ponteiro selvagem (não inicializado)

P: O que é mais importante sobre fundamentos de ponteiros? R: Entenda os conceitos centrais primeiro, depois reforce-os através de exemplos práticos.

📖 Resumo


📝 Exercícios

  1. Básico (Dificuldade ⭐): Declare uma variável int x = 10, depois declare um ponteiro int* p apontando para x. Exiba o valor de x e *p.

  2. Intermediário (Dificuldade ⭐⭐): Escreva uma função void addTen(int* p) que adiciona 10 à variável apontada pelo ponteiro. Teste-a em main.

  3. Desafio (Dificuldade ⭐⭐⭐): Escreva um programa que declare três variáveis int a, b, c, e três ponteiros apontando para cada uma delas. Use os ponteiros para alterar todas as três variáveis para 100, depois exiba-as.


9. 🚀 Próximo Passo

Agora que você aprendeu fundamentos de ponteiros, vamos avançar para Ponteiros e Arrays (Aula 23) — entendendo que nomes de arrays são ponteiros, e aritmética de ponteiros.

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%