Struct em Zig — O que é e Como Usar
Definição
Uma struct (estrutura) em Zig é um tipo composto que agrupa campos nomeados de diferentes tipos em uma única unidade. Structs são o bloco fundamental para organização de dados em Zig — desempenham o papel que classes têm em linguagens orientadas a objeto, mas sem herança. Em vez disso, Zig favorece composição e interfaces via comptime.
Por que Structs Importam
- Organização de dados: Agrupam dados relacionados com nomes significativos.
- Métodos: Podem conter funções associadas, encapsulando comportamento.
- Valores default: Campos podem ter valores padrão, simplificando a criação.
- Genéricos: Structs podem ser geradas em comptime, criando tipos genéricos.
Exemplo Prático
Struct Básica
const std = @import("std");
const Ponto = struct {
x: f64,
y: f64,
pub fn distancia(self: Ponto, outro: Ponto) f64 {
const dx = self.x - outro.x;
const dy = self.y - outro.y;
return @sqrt(dx * dx + dy * dy);
}
pub fn origem() Ponto {
return .{ .x = 0, .y = 0 };
}
};
pub fn main() void {
const a = Ponto{ .x = 3.0, .y = 4.0 };
const b = Ponto.origem();
std.debug.print("Distância: {d:.2}\n", .{a.distancia(b)}); // 5.00
}
Valores Default
const Config = struct {
porta: u16 = 8080,
host: []const u8 = "localhost",
max_conexoes: u32 = 100,
debug: bool = false,
};
pub fn main() void {
// Apenas os campos que diferem do padrão
const config = Config{
.porta = 3000,
.debug = true,
};
std.debug.print("Porta: {}, Debug: {}\n", .{ config.porta, config.debug });
}
Struct Genérica com Comptime
fn Pilha(comptime T: type) type {
return struct {
items: []T,
topo: usize,
allocator: std.mem.Allocator,
const Self = @This();
pub fn init(allocator: std.mem.Allocator, capacidade: usize) !Self {
return Self{
.items = try allocator.alloc(T, capacidade),
.topo = 0,
.allocator = allocator,
};
}
pub fn deinit(self: *Self) void {
self.allocator.free(self.items);
}
pub fn push(self: *Self, valor: T) !void {
if (self.topo >= self.items.len) return error.PilhaCheia;
self.items[self.topo] = valor;
self.topo += 1;
}
pub fn pop(self: *Self) ?T {
if (self.topo == 0) return null;
self.topo -= 1;
return self.items[self.topo];
}
};
}
Struct Anônima e Tupla
// Struct anônima (usada como literal)
const ponto = .{ .x = 10, .y = 20 };
// Tupla (struct anônima com campos indexados)
const tupla = .{ @as(u32, 42), "texto", true };
std.debug.print("Valor: {}\n", .{tupla[0]}); // 42
Tipos de Struct
| Tipo | Sintaxe | Característica |
|---|---|---|
| Normal | struct { } | Layout definido pelo compilador |
| Extern | extern struct { } | Layout compatível com C ABI |
| Packed | packed struct { } | Sem padding, campos bit a bit |
Armadilhas Comuns
- Esquecer o
self: Métodos de instância recebemselfcomo primeiro parâmetro. Métodos “estáticos” não recebem. - Mutabilidade: Para modificar campos, o parâmetro deve ser
*Self(ponteiro mutável), nãoSelf(cópia). - Ordem de inicialização: Todos os campos sem valor default devem ser inicializados. O compilador emite erro se algum for esquecido.
- Confundir tipos de struct:
struct,extern structepacked structtêm layouts de memória diferentes. Escolha o correto para cada uso.
Termos Relacionados
- Packed Struct — Structs com layout exato
- Enum — Enumerações
- Tagged Union — Unions discriminadas
- Comptime — Geração de tipos em compilação