---
title: "Ponteiros em Rust: Módulo std::ptr Guia | Rust Brasil"
url: "https://rustlang.com.br/stdlib/ptr-module/"
markdown_url: "https://rustlang.com.br/stdlib/ptr-module.MD"
description: "Guia completo do módulo std::ptr em Rust: raw pointers, null, read, write, copy e segurança de ponteiros. Referência em português."
date: "2026-02-23"
author: "Equipe Rust Brasil"
---

# Ponteiros em Rust: Módulo std::ptr Guia | Rust Brasil

Guia completo do módulo std::ptr em Rust: raw pointers, null, read, write, copy e segurança de ponteiros. Referência em português.


## Visao Geral do Modulo std::ptr

O modulo `std::ptr` fornece funcoes e tipos para trabalhar com **ponteiros raw** (`*const T` e `*mut T`) em Rust. Ponteiros raw sao o nivel mais baixo de acesso a memoria — eles nao carregam informacoes de lifetime, nao garantem validade e podem ser nulos.

Diferente de referencias (`&T` e `&mut T`), ponteiros raw:
- Podem ser nulos
- Podem apontar para memoria invalida
- Nao seguem regras de aliasing
- Podem ser criados em codigo safe, mas so podem ser **desreferenciados** em blocos `unsafe`

O uso principal de `std::ptr` e em:
- **FFI (Foreign Function Interface)** — interoperabilidade com C
- **Implementacao de estruturas de dados** — listas ligadas, alocadores customizados
- **Otimizacoes de baixo nivel** — quando as abstracoes safe tem custo inaceitavel

**Aviso:** Todo desreferenciamento de ponteiro raw requer `unsafe`. Use ponteiros raw apenas quando nao houver alternativa safe. Quando usar, documente as invariantes de seguranca com comentarios `// SAFETY:`.

---

## Tipos e Funcoes Principais

### Tipos de Ponteiro

| Tipo | Descricao |
|---|---|
| `*const T` | Ponteiro raw imutavel |
| `*mut T` | Ponteiro raw mutavel |
| `NonNull<T>` | Ponteiro nao-nulo (otimizado para `Option`) |

### Funcoes do Modulo

| Funcao | Descricao |
|---|---|
| `null::<T>()` | Cria um `*const T` nulo |
| `null_mut::<T>()` | Cria um `*mut T` nulo |
| `read(src)` | Le o valor apontado (unsafe) |
| `write(dst, val)` | Escreve um valor no destino (unsafe) |
| `read_unaligned(src)` | Le de endereco nao-alinhado (unsafe) |
| `write_unaligned(dst, val)` | Escreve em endereco nao-alinhado (unsafe) |
| `copy(src, dst, count)` | Copia `count` elementos (regioes podem se sobrepor, unsafe) |
| `copy_nonoverlapping(src, dst, count)` | Copia sem sobreposicao (unsafe) |
| `swap(a, b)` | Troca valores via ponteiros (unsafe) |
| `drop_in_place(ptr)` | Chama o destrutor do valor apontado (unsafe) |
| `addr_of!(expr)` | Cria `*const T` sem criar referencia |
| `addr_of_mut!(expr)` | Cria `*mut T` sem criar referencia |

### Metodos de Ponteiro

| Metodo | Descricao |
|---|---|
| `.is_null()` | Verifica se e nulo |
| `.offset(count)` | Desloca por `count` elementos (unsafe) |
| `.add(count)` | Avanca `count` elementos (unsafe) |
| `.sub(count)` | Retrocede `count` elementos (unsafe) |
| `.as_ref()` | Converte para `Option<&T>` (unsafe) |
| `.as_mut()` | Converte para `Option<&mut T>` (unsafe) |
| `.cast::<U>()` | Converte para `*const U` ou `*mut U` |

---

## Exemplos Praticos

### 1. Criando e Usando Ponteiros Raw

```rust
fn main() {
    let valor = 42i32;
    let referencia = &valor;

    // Criando ponteiros raw a partir de referencias (safe)
    let ptr_const: *const i32 = &valor;
    let ptr_const2: *const i32 = referencia as *const i32;

    // Verificando nulidade (safe)
    println!("E nulo? {}", ptr_const.is_null()); // false

    // Desreferenciar requer unsafe
    // SAFETY: ptr_const foi criado a partir de uma referencia valida
    // e o valor original ainda esta vivo
    unsafe {
        println!("Valor: {}", *ptr_const); // 42
    }

    // Ponteiro mutavel
    let mut numero = 10;
    let ptr_mut: *mut i32 = &mut numero;

    // SAFETY: ptr_mut aponta para 'numero' que esta vivo e acessivel
    unsafe {
        *ptr_mut = 20;
    }
    println!("Modificado: {numero}"); // 20

    // Ponteiro nulo
    let nulo: *const i32 = std::ptr::null();
    println!("E nulo? {}", nulo.is_null()); // true
}
```

### 2. NonNull — Ponteiro Garantidamente Nao-Nulo

```rust
use std::ptr::NonNull;

struct Node<T> {
    valor: T,
    proximo: Option<NonNull<Node<T>>>,
}

impl<T: std::fmt::Display> Node<T> {
    fn new(valor: T) -> Self {
        Node { valor, proximo: None }
    }

    fn imprimir_lista(&self) {
        print!("{}", self.valor);
        let mut atual = self.proximo;

        while let Some(ptr) = atual {
            // SAFETY: NonNull garante que o ponteiro nao e nulo,
            // e mantemos a invariante de que todos os nos sao validos
            unsafe {
                let node = ptr.as_ref();
                print!(" -> {}", node.valor);
                atual = node.proximo;
            }
        }
        println!();
    }
}

fn main() {
    let mut n1 = Node::new(1);
    let mut n2 = Node::new(2);
    let n3 = Node::new(3);

    // Conectando os nos
    n2.proximo = NonNull::new(&n3 as *const Node<i32> as *mut Node<i32>);
    n1.proximo = NonNull::new(&n2 as *const Node<i32> as *mut Node<i32>);

    n1.imprimir_lista(); // 1 -> 2 -> 3

    // NonNull tem o mesmo tamanho que *mut T
    println!(
        "Tamanho de Option<NonNull<i32>>: {} bytes",
        std::mem::size_of::<Option<NonNull<i32>>>()
    ); // 8 (mesma otimizacao que Option<&T>)
}
```

### 3. Aritmetica de Ponteiros e Acesso a Arrays

```rust
fn main() {
    let dados = [10, 20, 30, 40, 50];
    let ptr = dados.as_ptr();

    // Acessando elementos via aritmetica de ponteiros
    for i in 0..dados.len() {
        // SAFETY: i esta dentro dos limites do array,
        // entao ptr.add(i) aponta para um elemento valido
        unsafe {
            let valor = *ptr.add(i);
            println!("dados[{i}] = {valor}");
        }
    }

    // Copiando dados entre arrays
    let origem = [1u32, 2, 3, 4];
    let mut destino = [0u32; 4];

    // SAFETY: origem e destino nao se sobrepoe em memoria,
    // ambos tem pelo menos 4 elementos de u32
    unsafe {
        std::ptr::copy_nonoverlapping(
            origem.as_ptr(),
            destino.as_mut_ptr(),
            4,
        );
    }

    println!("Destino: {destino:?}"); // [1, 2, 3, 4]
}
```

### 4. Padrao FFI — Interoperabilidade com C

```rust
use std::ffi::CStr;
use std::os::raw::c_char;

// Simulando uma funcao C que retorna uma string
fn funcao_c_simulada() -> *const c_char {
    b"Resultado da funcao C\0".as_ptr() as *const c_char
}

// Simulando uma funcao C que recebe um ponteiro para preencher
fn c_preencher_buffer(buf: *mut i32, tamanho: usize) {
    for i in 0..tamanho {
        // SAFETY: assumimos que buf aponta para memoria valida
        // com pelo menos 'tamanho' elementos
        unsafe {
            buf.add(i).write(i as i32 * 100);
        }
    }
}

fn main() {
    // Recebendo string de C
    let ptr_c = funcao_c_simulada();
    if !ptr_c.is_null() {
        // SAFETY: verificamos que nao e nulo e a string
        // termina com null byte
        let texto = unsafe { CStr::from_ptr(ptr_c) };
        println!("{}", texto.to_string_lossy());
    }

    // Passando buffer para funcao C preencher
    let mut buffer = vec![0i32; 5];

    // SAFETY: buffer tem exatamente 5 elementos alocados
    c_preencher_buffer(buffer.as_mut_ptr(), buffer.len());

    println!("Buffer: {buffer:?}"); // [0, 100, 200, 300, 400]
}
```

### 5. addr_of! e addr_of_mut! para Campos Nao-Alinhados

```rust
use std::ptr;

#[repr(packed)]
struct Pacote {
    flag: u8,
    valor: u32,  // Nao alinhado em 4 bytes por causa de #[repr(packed)]
    dados: u64,
}

fn main() {
    let pacote = Pacote {
        flag: 1,
        valor: 42,
        dados: 0xDEADBEEF,
    };

    // ERRADO: &pacote.valor criaria uma referencia nao-alinhada (UB!)
    // let ref_valor = &pacote.valor; // Isso e UB em repr(packed)!

    // CORRETO: addr_of! cria um ponteiro raw sem criar referencia
    let ptr_valor = ptr::addr_of!(pacote.valor);

    // SAFETY: usamos read_unaligned porque o campo pode nao estar alinhado
    let valor = unsafe { ptr::read_unaligned(ptr_valor) };
    println!("Valor: {valor}"); // 42

    let ptr_dados = ptr::addr_of!(pacote.dados);
    let dados = unsafe { ptr::read_unaligned(ptr_dados) };
    println!("Dados: {dados:#X}"); // 0xDEADBEEF
}
```

---

## Padroes Comuns

### Verificacao de Nulidade Antes de Usar

Sempre verifique ponteiros recebidos de FFI:

```rust
fn processar_ponteiro(ptr: *const i32) -> Option<i32> {
    if ptr.is_null() {
        return None;
    }
    // SAFETY: acabamos de verificar que nao e nulo.
    // Assumimos que o chamador garante que o ponteiro
    // aponta para memoria valida.
    Some(unsafe { *ptr })
}
```

### Convertendo Entre Ponteiros e Referencias

```rust
fn ponteiro_para_referencia<'a>(ptr: *const i32) -> Option<&'a i32> {
    // SAFETY: as_ref() retorna None se o ponteiro for nulo.
    // O chamador deve garantir que o ponteiro aponta para
    // memoria valida pelo lifetime 'a.
    unsafe { ptr.as_ref() }
}
```

### Usando NonNull como Campo de Struct

```rust
use std::ptr::NonNull;

struct Buffer {
    ptr: NonNull<u8>,
    len: usize,
}

// SAFETY: NonNull nao implementa Send/Sync automaticamente
// Implementamos apenas se tivermos ownership exclusivo
unsafe impl Send for Buffer {}
unsafe impl Sync for Buffer {}
```

---

## Quando Usar (e Quando Nao Usar)

**Use `std::ptr` quando:**
- Estiver fazendo FFI com C/C++
- Implementando estruturas de dados com ponteiros (listas, arvores)
- Precisar de `addr_of!` para structs `#[repr(packed)]`
- Implementando alocadores de memoria customizados
- Otimizacoes de performance comprovadamente necessarias

**Nao use `std::ptr` quando:**
- Referencias (`&T`, `&mut T`) resolverem o problema
- `Box`, `Rc`, `Arc` atenderem a necessidade de ownership
- Estiver tentando contornar o borrow checker (repense o design!)
- `Vec`, `HashMap` ou outra colecao da stdlib for suficiente

**Regra de ouro:** Se voce precisa de ponteiros raw e nao esta fazendo FFI ou implementando uma estrutura de dados fundamental, provavelmente existe uma alternativa safe melhor.

---

## Veja Tambem

- [Unsafe Rust](/artigos/unsafe-rust/) — guia completo sobre blocos unsafe
- [Modulo std::mem](/stdlib/mem-module/) — funcoes de manipulacao de memoria
- [Modulo std::marker](/stdlib/marker-module/) — traits como Send e Sync para ponteiros
- [Modulo std::any](/stdlib/any-module/) — alternativa safe para type erasure
- [Modulo std::convert](/stdlib/convert-module/) — conversoes seguras entre tipos
- [Documentacao oficial — std::ptr](https://doc.rust-lang.org/std/ptr/index.html)
