Undefined em Zig — O que é e Como Usar

Undefined em Zig — O que é e Como Usar

Definição

O valor undefined em Zig é um marcador especial que indica que uma variável não foi inicializada. Quando você atribui undefined a uma variável, está explicitamente dizendo ao compilador: “eu sei que este valor não tem conteúdo válido ainda, e me comprometo a inicializá-lo antes de usar”.

Em modo Debug e ReleaseSafe, variáveis undefined são preenchidas com 0xAA (padrão facilmente reconhecível em depuração). Em ReleaseFast e ReleaseSmall, undefined permite que o compilador otimize livremente, podendo resultar em qualquer valor.

Por que Undefined Importa

  1. Performance: Evita inicialização desnecessária de buffers grandes que serão preenchidos imediatamente.
  2. Explicitação: Torna claro que a não-inicialização é intencional, não um bug.
  3. Detecção de bugs: Em modo Debug, o padrão 0xAA ajuda a identificar uso acidental.
  4. Compatibilidade com C: Permite o mesmo padrão de “declara depois inicializa” comum em C.

Exemplo Prático

Uso com Buffers

const std = @import("std");

pub fn main() !void {
    // Buffer que será preenchido pela leitura
    var buffer: [1024]u8 = undefined;

    const stdin = std.io.getStdIn();
    const bytes_lidos = try stdin.read(&buffer);

    // Agora só a parte preenchida é válida
    const entrada = buffer[0..bytes_lidos];
    std.debug.print("Lido: {s}\n", .{entrada});
}

Uso com Arrays Calculados

fn calcularTabela() [256]u8 {
    var tabela: [256]u8 = undefined;
    for (0..256) |i| {
        tabela[i] = @intCast(i ^ 0xFF); // Preenche cada posição
    }
    return tabela;
}

const TABELA = calcularTabela();

Uso com Structs

const Conexao = struct {
    socket: std.posix.socket_t,
    buffer: [4096]u8,
    bytes_recebidos: usize,

    pub fn init(endereco: []const u8) !Conexao {
        var self: Conexao = undefined;
        self.socket = try conectar(endereco);
        self.bytes_recebidos = 0;
        // buffer será preenchido quando dados chegarem
        return self;
    }
};

Comparação: undefined vs Zero-init

// undefined — sem custo, mas perigoso se não inicializar
var buffer1: [1_000_000]u8 = undefined;

// Zero-init — seguro, mas gasta tempo zerando 1MB
var buffer2: [1_000_000]u8 = std.mem.zeroes([1_000_000]u8);

// Ou com @memset
var buffer3: [1_000_000]u8 = undefined;
@memset(&buffer3, 0);

O que Acontece em Cada Modo

ModoValor de undefinedVerificação
Debug0xAA repetidoSim (panic ao detectar uso)
ReleaseSafe0xAA repetidoSim
ReleaseFastLixo de memóriaNão
ReleaseSmallLixo de memóriaNão

Armadilhas Comuns

  • Ler antes de inicializar: Em Release, undefined pode ser qualquer valor — ler sem inicializar é comportamento indefinido. Em Debug, causa panic.
  • Passar undefined para funções: Se uma função espera um valor válido e recebe undefined, o comportamento é indefinido.
  • Confundir com null: null é um valor válido para optionals; undefined significa “sem valor algum”.
  • Uso excessivo: Não use undefined como “default” para tudo. Se há um valor inicial razoável, use-o.
  • Retornar undefined: Retornar undefined de uma função é quase sempre um bug. O chamador esperará um valor válido.

Termos Relacionados

Tutoriais Relacionados

Continue aprendendo Zig

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