void em Zig — O que é e Como Usar
Definição
void é o tipo em Zig que representa ausência de valor. Ele ocupa zero bytes de memória e é usado principalmente como tipo de retorno de funções que não produzem resultado. Diferente de C, onde void é especial e não pode ser usado como valor, em Zig void é um tipo de primeira classe — pode ser atribuído a variáveis, usado em genéricos e armazenado em structs.
O valor literal de void é {}.
Por que void Importa
- Retorno de funções: Indica que uma função executa efeito colateral sem produzir valor.
- Genéricos: Permite criar contêineres onde o “valor” é ignorado (ex: HashSet usando HashMap com valor void).
- Otimização de memória: Campos void em structs não ocupam espaço.
- Consistência do sistema de tipos: Todo tipo em Zig pode ser usado uniformemente, incluindo void.
Exemplo Prático
Função com Retorno void
const std = @import("std");
fn saudar(nome: []const u8) void {
std.debug.print("Olá, {s}!\n", .{nome});
// Sem return explícito — retorna void implicitamente
}
fn processar(dados: []u8) void {
for (dados) |*byte| {
byte.* = byte.* +% 1; // incrementa cada byte
}
return; // return explícito de void (opcional)
}
pub fn main() void {
saudar("Zig Brasil");
var buffer = [_]u8{ 1, 2, 3 };
processar(&buffer);
std.debug.print("{any}\n", .{buffer}); // { 2, 3, 4 }
}
HashSet com void como Valor
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// HashMap com valor void funciona como um Set
var conjunto = std.AutoHashMap([]const u8, void).init(allocator);
defer conjunto.deinit();
try conjunto.put("zig", {});
try conjunto.put("rust", {});
try conjunto.put("go", {});
// Verificar pertencimento
const tem_zig = conjunto.contains("zig");
std.debug.print("Tem zig: {}\n", .{tem_zig}); // true
}
void em Tipos Genéricos
const std = @import("std");
fn Wrapper(comptime T: type) type {
return struct {
valor: T,
pub fn init(v: T) @This() {
return .{ .valor = v };
}
pub fn temValor() bool {
return T != void;
}
};
}
pub fn main() void {
const com_valor = Wrapper(u32).init(42);
const sem_valor = Wrapper(void).init({});
std.debug.print("Com valor: {}\n", .{Wrapper(u32).temValor()}); // true
std.debug.print("Sem valor: {}\n", .{Wrapper(void).temValor()}); // false
_ = com_valor;
_ = sem_valor;
}
void vs noreturn
| Tipo | Significado | Exemplo |
|---|---|---|
void | Retorna, mas sem valor útil | fn processar() void |
noreturn | Nunca retorna | fn sair() noreturn |
Armadilhas Comuns
- void vs noreturn:
voidretorna normalmente (sem valor);noreturnindica que a função nunca retorna (ex:@panic, loop infinito,std.process.exit). - Literal void: O valor de void é
{}, nãonull.nullé para optionals. - Comparação: Dois valores void são sempre iguais (
{} == {}étrue). - Em error unions:
!voidsignifica “pode retornar erro ou void”. É o tipo de retorno mais comum para funções que podem falhar sem produzir resultado.
Termos Relacionados
- noreturn — Tipo para funções que nunca retornam
- Optional — Tipo que pode ser nulo (diferente de void)
- Error Union —
!voidpara funções que podem falhar - Struct — Campos void ocupam zero bytes