---
title: "Converter Ponteiros C para Zig"
url: "https://ziglang.com.br/tutoriais/converter-ponteiros-c-para-zig/"
markdown_url: "https://ziglang.com.br/tutoriais/converter-ponteiros-c-para-zig.MD"
description: "Guia prático para converter ponteiros C para tipos Zig. Cobertura de ponteiros simples, arrays, strings, void*, ponteiros nullable, sentinela e casts entre tipos de ponteiro."
date: "2026-02-21"
author: "Zig Brasil"
---

# Converter Ponteiros C para Zig

Guia prático para converter ponteiros C para tipos Zig. Cobertura de ponteiros simples, arrays, strings, void*, ponteiros nullable, sentinela e casts entre tipos de ponteiro.


## Introdução

A conversão de ponteiros entre C e Zig é uma das tarefas mais comuns na interoperabilidade e migração. Zig tem um sistema de ponteiros mais rico que C — com distinção entre ponteiros simples, muitos-itens, nullable, e com sentinela. Este guia cobre todas as conversões necessárias.

Para interoperabilidade geral, veja [Interoperabilidade C-Zig](/tutoriais/zig-c-interoperabilidade/). Para chamadas de funções C, consulte [Chamar Funções C de Zig](/receitas/zig-chamar-funcao-c/).

## Pré-requisitos

- Zig instalado (versão 0.13+). Veja [Como Instalar Zig](/tutoriais/como-instalar-zig/)
- Conhecimento de ponteiros em C
- Familiaridade com Zig. Consulte [Introdução ao Zig](/tutoriais/introducao-ao-zig/)

## Tipos de Ponteiros

### Mapeamento C para Zig

| C | Zig | Descrição |
|---|-----|-----------|
| `int*` (non-null) | `*i32` | Ponteiro para um elemento |
| `int*` (nullable) | `?*i32` | Ponteiro opcional |
| `int*` (array) | `[*]i32` | Ponteiro para muitos elementos |
| `const int*` | `[*]const i32` | Ponteiro constante para muitos |
| `int[]` (param) | `[]i32` | Slice (ptr + len) |
| `const char*` | `[*:0]const u8` | String C null-terminated |
| `void*` | `*anyopaque` | Ponteiro opaco |
| `void*` (nullable) | `?*anyopaque` | Ponteiro opaco nullable |

## Ponteiro Simples

### C

```c
void incrementar(int* valor) {
    (*valor)++;
}

int x = 41;
incrementar(&x);
// x == 42
```

### Zig

```zig
fn incrementar(valor: *i32) void {
    valor.* += 1;
}

var x: i32 = 41;
incrementar(&x);
// x == 42
```

O operador de dereference em Zig é `.*` (pós-fixo), em vez de `*` (pré-fixo) como em C.

## Ponteiros para Arrays

### C

```c
void preencher(int* arr, size_t n) {
    for (size_t i = 0; i < n; i++) {
        arr[i] = (int)i;
    }
}
```

### Zig com Slice (preferido)

```zig
fn preencher(arr: []i32) void {
    for (arr, 0..) |*item, i| {
        item.* = @intCast(i);
    }
}
```

Slices (`[]T`) são a forma idiomática em Zig — eles carregam o tamanho junto com o ponteiro, eliminando a necessidade de passar `size_t n` separadamente.

### Zig com Many-Item Pointer (para interop C)

```zig
fn preencher(arr: [*]i32, n: usize) void {
    for (0..n) |i| {
        arr[i] = @intCast(i);
    }
}
```

### Converter entre os dois

```zig
// Many-item pointer + length -> Slice
const slice: []i32 = arr[0..n];

// Slice -> Many-item pointer
const ptr: [*]i32 = slice.ptr;
const len: usize = slice.len;
```

## Strings C (null-terminated)

### C

```c
size_t comprimento(const char* str) {
    return strlen(str);
}
```

### Zig

```zig
// Receber string C null-terminated
fn comprimento(str: [*:0]const u8) usize {
    return std.mem.len(str);
}

// Converter para slice Zig (sem null terminator)
fn processar(str_c: [*:0]const u8) void {
    const str: []const u8 = std.mem.span(str_c);
    std.debug.print("Tamanho: {} - Conteúdo: {s}\n", .{ str.len, str });
}

// Converter slice Zig para string C (para chamar funções C)
fn chamarC(allocator: std.mem.Allocator, str_zig: []const u8) !void {
    const str_c = try allocator.dupeZ(u8, str_zig); // adiciona null terminator
    defer allocator.free(str_c);
    c.funcao_c(str_c.ptr);
}
```

## void* (Ponteiro Opaco)

### C

```c
void* contexto = &meus_dados;
MeusDados* dados = (MeusDados*)contexto;
```

### Zig

```zig
// Converter para anyopaque
const contexto: *anyopaque = @ptrCast(&meus_dados);

// Converter de volta
const dados: *MeusDados = @ptrCast(@alignCast(contexto));
```

### Uso comum: callbacks com contexto

```zig
const c = @cImport(@cInclude("minha_lib.h"));

fn meuCallback(contexto: ?*anyopaque) callconv(.C) void {
    if (contexto) |ctx| {
        const dados: *MeusDados = @ptrCast(@alignCast(ctx));
        dados.processar();
    }
}

pub fn registrar(dados: *MeusDados) void {
    c.registrar_callback(meuCallback, @ptrCast(dados));
}
```

## Ponteiros Nullable

### C

```c
// Em C, QUALQUER ponteiro pode ser NULL
int* buscar(int id) {
    if (id == 0) return NULL;
    // ...
}

int* resultado = buscar(42);
if (resultado != NULL) {
    printf("%d\n", *resultado);
}
```

### Zig

```zig
// Em Zig, nullabilidade é explícita
fn buscar(id: i32) ?*i32 {
    if (id == 0) return null;
    // ...
}

if (buscar(42)) |resultado| {
    std.debug.print("{}\n", .{resultado.*});
} else {
    std.debug.print("Não encontrado\n", .{});
}
```

## Aritmética de Ponteiros

### C

```c
int arr[10];
int* ptr = arr;
int* terceiro = ptr + 2;
ptrdiff_t diff = terceiro - ptr;
```

### Zig

```zig
var arr: [10]i32 = undefined;
const ptr: [*]i32 = &arr;
const terceiro = ptr + 2;
// Aritmética de ponteiros é possível com [*]T

// Preferir slices:
const slice: []i32 = &arr;
const terceiro_valor = slice[2];
```

## Conversão em Contexto de @cImport

Quando você usa `@cImport`, Zig traduz automaticamente os tipos C para tipos Zig:

```zig
const c = @cImport(@cInclude("sqlite3.h"));

pub fn exemplo() !void {
    var db: ?*c.sqlite3 = null;
    const rc = c.sqlite3_open("banco.db", &db);

    if (rc != c.SQLITE_OK) {
        if (db) |d| {
            const msg = c.sqlite3_errmsg(d);
            const msg_slice = std.mem.span(msg);
            std.debug.print("Erro: {s}\n", .{msg_slice});
        }
        return error.SqliteError;
    }
    defer _ = c.sqlite3_close(db);
}
```

## Tabela de Conversões Comuns

| De | Para | Método |
|----|------|--------|
| `*T` | `*anyopaque` | `@ptrCast(ptr)` |
| `*anyopaque` | `*T` | `@ptrCast(@alignCast(ptr))` |
| `[*]T` | `[]T` | `ptr[0..len]` |
| `[]T` | `[*]T` | `slice.ptr` |
| `[*:0]u8` | `[]u8` | `std.mem.span(ptr)` |
| `[]u8` | `[*:0]u8` | `allocator.dupeZ(u8, slice)` |
| `*T` | `?*T` | Implícito |
| `?*T` | `*T` | `opt_ptr orelse return error.NullPtr` |
| `*[N]T` | `[]T` | `ptr[0..]` ou `ptr` (coerção) |
| `usize` | `*T` | `@ptrFromInt(addr)` |
| `*T` | `usize` | `@intFromPtr(ptr)` |

## Conclusão

A conversão de ponteiros entre C e Zig é direta quando você entende o mapeamento de tipos. A regra geral: use slices (`[]T`) dentro de código Zig puro, e many-item pointers (`[*]T`) ou sentinel pointers (`[*:0]T`) na fronteira com C.

Para mais sobre interop C, veja [Interoperabilidade C-Zig](/tutoriais/zig-c-interoperabilidade/), [Chamar Funções C de Zig](/receitas/zig-chamar-funcao-c/) e [Portar uma Biblioteca C para Zig](/tutoriais/zig-portar-biblioteca-c/).
