Slice em Zig — O que é e Como Usar

Slice em Zig — O que é e Como Usar

Definição

Um Slice em Zig é uma referência a uma sequência contígua de elementos na memória, representada pelo tipo []T. Internamente, um slice é composto por dois campos: um ponteiro para o início dos dados e um comprimento (length). Slices não possuem os dados — eles apenas apontam para dados que existem em outro lugar (um array, memória alocada no heap, etc.).

Slices são o tipo mais comum para trabalhar com sequências de dados em Zig, substituindo o padrão de C de “ponteiro + tamanho separado”.

Por que Slices Importam

  1. Segurança: Carregam o tamanho junto do ponteiro, permitindo verificação de limites.
  2. Ergonomia: Suportam sintaxe de indexação (slice[i]), iteração (for) e fatiamento (slice[a..b]).
  3. Interoperabilidade: Podem ser criados a partir de arrays, ponteiros ou memória alocada.
  4. String literals: Em Zig, strings são []const u8 — ou seja, slices de bytes.

Exemplo Prático

Criando Slices

const std = @import("std");

pub fn main() void {
    // A partir de um array
    var array = [_]u32{ 10, 20, 30, 40, 50 };
    const slice: []u32 = array[1..4]; // [20, 30, 40]

    std.debug.print("Tamanho: {}\n", .{slice.len}); // 3
    std.debug.print("Primeiro: {}\n", .{slice[0]});  // 20

    // Iteração
    for (slice) |valor| {
        std.debug.print("{} ", .{valor});
    }
}

Slices como Parâmetros

fn soma(numeros: []const u32) u64 {
    var total: u64 = 0;
    for (numeros) |n| {
        total += n;
    }
    return total;
}

pub fn main() void {
    const array = [_]u32{ 1, 2, 3, 4, 5 };
    const resultado = soma(&array); // Array coerce para slice
    std.debug.print("Soma: {}\n", .{resultado}); // 15
}

Fatiamento (Slicing)

const texto: []const u8 = "Zig Brasil";

const zig = texto[0..3];     // "Zig"
const brasil = texto[4..10]; // "Brasil"
const tudo = texto[0..];     // "Zig Brasil" (até o fim)

Slice de Memória Alocada

fn criarBuffer(allocator: std.mem.Allocator, tamanho: usize) ![]u8 {
    const buffer = try allocator.alloc(u8, tamanho);
    @memset(buffer, 0); // Inicializa com zeros
    return buffer;
}

Tipos de Slice

TipoDescrição
[]TSlice mutável
[]const TSlice somente leitura
[:0]u8Slice terminado em sentinel (zero)
[*]TMany-pointer (sem tamanho conhecido)

Representação Interna

[]u32 é equivalente a:

struct {
    ptr: [*]u32,  // Ponteiro para o primeiro elemento
    len: usize,   // Número de elementos
}

Tamanho total: 2 * @sizeOf(usize) = 16 bytes em 64-bit

Armadilhas Comuns

  • Slice não possui os dados: Se o array original sair do escopo, o slice se torna um dangling pointer. Cuidado com slices de arrays locais retornados de funções.
  • Indexação fora dos limites: Acessar slice[slice.len] ou índices negativos causa panic em modo Debug/ReleaseSafe.
  • Confundir []T com [N]T: [N]T é um array de tamanho fixo (valor); []T é um slice (referência).
  • Modificar slice const: []const u8 não permite modificação. Tente []u8 se precisar alterar os dados.
  • Esquecer de liberar: Slices de memória alocada (allocator.alloc) devem ser liberados com allocator.free.

Termos Relacionados

Tutoriais Relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.