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
- Segurança: Carregam o tamanho junto do ponteiro, permitindo verificação de limites.
- Ergonomia: Suportam sintaxe de indexação (
slice[i]), iteração (for) e fatiamento (slice[a..b]). - Interoperabilidade: Podem ser criados a partir de arrays, ponteiros ou memória alocada.
- 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
| Tipo | Descrição |
|---|---|
[]T | Slice mutável |
[]const T | Slice somente leitura |
[:0]u8 | Slice terminado em sentinel (zero) |
[*]T | Many-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
[]Tcom[N]T:[N]Té um array de tamanho fixo (valor);[]Té um slice (referência). - Modificar slice const:
[]const u8não permite modificação. Tente[]u8se precisar alterar os dados. - Esquecer de liberar: Slices de memória alocada (
allocator.alloc) devem ser liberados comallocator.free.
Termos Relacionados
- Sentinel — Arrays e slices terminados por sentinela
- Pointer Types — Tipos de ponteiro (T, []T, []T)
- Stack vs Heap — Onde os dados vivem
- usize — Tipo do índice e comprimento