Cheatsheet: Arrays e Slices em Zig
Arrays são coleções de tamanho fixo determinado em tempo de compilação. Slices são referências a segmentos contíguos de memória com tamanho conhecido em runtime.
Declaração de Arrays
// Array com tipo explícito
const nums: [5]i32 = .{ 1, 2, 3, 4, 5 };
// Array com tamanho inferido
const letras = [_]u8{ 'a', 'b', 'c', 'd' };
// Array preenchido com valor constante
const zeros: [100]u8 = .{0} ** 100;
const uns: [10]i32 = .{1} ** 10;
// Array não inicializado
var buffer: [1024]u8 = undefined;
// Array com sentinela
const c_str: [5:0]u8 = .{ 'h', 'e', 'l', 'l', 'o' };
// c_str[5] == 0 (sentinela)
// Array multidimensional
const matrix: [3][4]i32 = .{
.{ 1, 2, 3, 4 },
.{ 5, 6, 7, 8 },
.{ 9, 10, 11, 12 },
};
Acesso a Elementos
const arr = [_]i32{ 10, 20, 30, 40, 50 };
// Acesso por índice
const primeiro = arr[0]; // 10
const terceiro = arr[2]; // 30
const ultimo = arr[arr.len - 1]; // 50
// Tamanho
const tam = arr.len; // 5 (comptime_int)
// Acesso a array mutável
var mut_arr = [_]i32{ 1, 2, 3 };
mut_arr[1] = 20; // agora {1, 20, 3}
Criação de Slices
const arr = [_]i32{ 1, 2, 3, 4, 5 };
// Slice a partir de array
const s1: []const i32 = &arr; // array inteiro
const s2: []const i32 = arr[1..4]; // {2, 3, 4}
const s3: []const i32 = arr[2..]; // {3, 4, 5}
const s4: []const i32 = arr[0..3]; // {1, 2, 3}
// Slice mutável
var mut_arr = [_]i32{ 1, 2, 3, 4, 5 };
var mut_slice: []i32 = &mut_arr;
mut_slice[0] = 100; // modifica o array original
// Slice de slice
const sub = s1[1..3]; // {2, 3}
// Propriedades do slice
const ptr = s1.ptr; // [*]const i32
const len = s1.len; // usize
Iteração
const arr = [_]i32{ 10, 20, 30, 40, 50 };
// Iterar sobre valores
for (arr) |valor| {
std.debug.print("{} ", .{valor});
}
// Iterar com índice
for (arr, 0..) |valor, i| {
std.debug.print("[{}]={} ", .{ i, valor });
}
// Iterar com ponteiro (para modificar)
var mut = [_]i32{ 1, 2, 3 };
for (&mut) |*elem| {
elem.* *= 2;
}
// mut agora é {2, 4, 6}
// Iterar múltiplos arrays simultaneamente
const a = [_]i32{ 1, 2, 3 };
const b = [_]i32{ 10, 20, 30 };
for (a, b) |va, vb| {
std.debug.print("{} + {} = {}\n", .{ va, vb, va + vb });
}
// Iteração reversa com std.mem
const rev = std.mem.reverseIterator(&arr);
Operações com std.mem
const std = @import("std");
const arr = [_]i32{ 5, 3, 1, 4, 2 };
// Copiar
var dest: [5]i32 = undefined;
@memcpy(&dest, &arr);
// Preencher
var buf: [10]u8 = undefined;
@memset(&buf, 0); // preencher com zeros
// Comparar
const a = [_]u8{ 1, 2, 3 };
const b = [_]u8{ 1, 2, 3 };
const iguais = std.mem.eql(u8, &a, &b); // true
// Buscar
const dados = [_]i32{ 1, 2, 3, 4, 5 };
const pos = std.mem.indexOf(i32, &dados, &[_]i32{ 3, 4 }); // ?usize = 2
// Contar
const texto = "banana";
const count = std.mem.count(u8, texto, "an"); // 2
// Substituir (in-place)
var texto_mut = [_]u8{ 'a', 'b', 'c', 'a', 'b', 'c' };
const n = std.mem.replace(u8, &texto_mut, "ab", "XY", &texto_mut);
Ordenação
const std = @import("std");
var numeros = [_]i32{ 5, 3, 1, 4, 2 };
// Ordenar em ordem crescente
std.mem.sort(i32, &numeros, {}, std.sort.asc(i32));
// numeros agora é {1, 2, 3, 4, 5}
// Ordenar em ordem decrescente
std.mem.sort(i32, &numeros, {}, std.sort.desc(i32));
// numeros agora é {5, 4, 3, 2, 1}
// Ordenação customizada
const Pessoa = struct {
nome: []const u8,
idade: u32,
};
var pessoas = [_]Pessoa{
.{ .nome = "Carlos", .idade = 30 },
.{ .nome = "Ana", .idade = 25 },
.{ .nome = "Bruno", .idade = 35 },
};
std.mem.sort(Pessoa, &pessoas, {}, struct {
fn compare(_: void, a: Pessoa, b: Pessoa) bool {
return a.idade < b.idade;
}
}.compare);
Arrays Dinâmicos (ArrayList)
const std = @import("std");
pub fn exemplo(allocator: std.mem.Allocator) !void {
// Criar ArrayList
var lista = std.ArrayList(i32).init(allocator);
defer lista.deinit();
// Adicionar elementos
try lista.append(10);
try lista.append(20);
try lista.append(30);
// Adicionar múltiplos
try lista.appendSlice(&[_]i32{ 40, 50 });
// Inserir em posição
try lista.insert(2, 25); // inserir 25 na posição 2
// Remover
const removido = lista.orderedRemove(1); // remove posição 1
_ = lista.swapRemove(0); // remove posição 0 (mais rápido, não preserva ordem)
// Acessar
const slice = lista.items; // []i32
const elem = lista.items[0];
const tam = lista.items.len;
_ = elem;
_ = tam;
// Redimensionar
try lista.resize(10); // tamanho = 10
// Transferir propriedade
const owned = try lista.toOwnedSlice();
defer allocator.free(owned);
}
HashMap
const std = @import("std");
pub fn exemplo(allocator: std.mem.Allocator) !void {
// HashMap com chave string
var mapa = std.StringHashMap(i32).init(allocator);
defer mapa.deinit();
// Inserir
try mapa.put("um", 1);
try mapa.put("dois", 2);
try mapa.put("três", 3);
// Buscar
if (mapa.get("dois")) |valor| {
std.debug.print("dois = {}\n", .{valor});
}
// Verificar existência
const existe = mapa.contains("um"); // true
_ = existe;
// Remover
_ = mapa.remove("um");
// Iterar
var it = mapa.iterator();
while (it.next()) |entry| {
std.debug.print("{s} = {}\n", .{ entry.key_ptr.*, entry.value_ptr.* });
}
// Tamanho
const tam = mapa.count();
_ = tam;
}
Operações Comptime com Arrays
// Concatenação em comptime
const a = [_]i32{ 1, 2, 3 };
const b = [_]i32{ 4, 5, 6 };
const c = a ++ b; // [6]i32{ 1, 2, 3, 4, 5, 6 }
// Repetição em comptime
const rep = [_]u8{ 0xAB } ** 4; // { 0xAB, 0xAB, 0xAB, 0xAB }
// Inicialização com função comptime
const tabela = blk: {
var t: [256]u8 = undefined;
for (&t, 0..) |*elem, i| {
elem.* = @intCast(i);
}
break :blk t;
};
// Array gerado com comptime
fn quadrados(comptime N: usize) [N]i32 {
var result: [N]i32 = undefined;
for (&result, 0..) |*elem, i| {
elem.* = @intCast(i * i);
}
return result;
}
const quads = quadrados(5); // { 0, 1, 4, 9, 16 }
Padrões Comuns
// Verificar se array está vazio
const vazio = slice.len == 0;
// Primeiro e último elemento seguros
const primeiro = if (slice.len > 0) slice[0] else null;
// Encontrar máximo/mínimo
const max = std.mem.max(i32, &arr);
const min = std.mem.min(i32, &arr);
// Converter array para slice
const arr2 = [_]i32{ 1, 2, 3 };
const slice2: []const i32 = &arr2;
// Slice com sentinela para interop com C
const sentinel: [:0]const u8 = "hello";
const c_ptr: [*:0]const u8 = sentinel.ptr;
_ = c_ptr;
Veja Também
- Tipos de Dados — Todos os tipos em Zig
- Strings — Strings são slices de
u8 - Ponteiros — Relação entre slices e ponteiros
- Allocators — Alocação dinâmica
- Std Library — Funções essenciais da biblioteca padrão