@intFromPtr em Zig — Referência e Exemplos

@intFromPtr em Zig

O @intFromPtr converte um ponteiro para seu valor numérico de endereço de memória, representado como um usize. Esse builtin é essencial para programação de baixo nível, incluindo desenvolvimento de sistemas operacionais, drivers e alocadores de memória personalizados.

Sintaxe

@intFromPtr(ptr: anytype) usize

O que faz

O @intFromPtr extrai o endereço numérico de memória contido em um ponteiro e o retorna como um valor usize. Essa operação é o inverso de @ptrFromInt. O valor retornado representa o endereço de memória virtual onde o dado apontado reside.

Esta é uma operação de baixo nível que deve ser usada com cuidado, pois trabalhar diretamente com endereços de memória pode facilmente levar a comportamento indefinido se usado incorretamente.

Parâmetros

  • ptr (anytype): Um ponteiro de qualquer tipo. Pode ser um ponteiro simples (*T), um ponteiro para muitos ([*]T), um slice ([]T) — neste caso, retorna o endereço do início — ou qualquer outra variante de ponteiro.

Valor de retorno

Retorna um usize contendo o endereço numérico de memória do ponteiro.

Exemplos práticos

Exemplo 1: Obtendo o endereço de uma variável

const std = @import("std");

test "endereço de variável" {
    var valor: u32 = 42;
    const ptr = &valor;
    const endereco = @intFromPtr(ptr);

    std.debug.print("Valor: {}\n", .{valor});
    std.debug.print("Endereço: 0x{x}\n", .{endereco});

    // O endereço é um número positivo diferente de zero
    try std.testing.expect(endereco != 0);

    // Converter de volta para ponteiro funciona
    const ptr_recuperado: *u32 = @ptrFromInt(endereco);
    try std.testing.expect(ptr_recuperado.* == 42);
}

Exemplo 2: Verificação de alinhamento

const std = @import("std");

fn estaAlinhado(ptr: anytype, comptime alinhamento: usize) bool {
    const endereco = @intFromPtr(ptr);
    return endereco % alinhamento == 0;
}

test "verificar alinhamento" {
    var buffer: [64]u8 align(16) = undefined;
    const ptr = &buffer;

    // Buffer declarado com align(16) deve estar alinhado a 16 bytes
    try std.testing.expect(estaAlinhado(ptr, 16));
    try std.testing.expect(estaAlinhado(ptr, 8));
    try std.testing.expect(estaAlinhado(ptr, 4));
}

Exemplo 3: Aritmética de ponteiros para alocador personalizado

const std = @import("std");

const AlocadorBump = struct {
    buffer: []u8,
    offset: usize,

    fn init(buffer: []u8) AlocadorBump {
        return .{ .buffer = buffer, .offset = 0 };
    }

    fn alocar(self: *AlocadorBump, tamanho: usize, comptime alinhamento: usize) ?[*]u8 {
        // Calcular endereço alinhado usando aritmética de ponteiro
        const ptr_atual = @intFromPtr(self.buffer.ptr) + self.offset;
        const alinhado = (ptr_atual + alinhamento - 1) & ~(@as(usize, alinhamento) - 1);
        const desperdicio = alinhado - ptr_atual;
        const total = desperdicio + tamanho;

        if (self.offset + total > self.buffer.len) return null;

        self.offset += total;
        return @ptrFromInt(alinhado);
    }
};

test "alocador bump" {
    var buffer: [1024]u8 = undefined;
    var alocador = AlocadorBump.init(&buffer);

    const ptr1 = alocador.alocar(32, 8);
    try std.testing.expect(ptr1 != null);
    try std.testing.expect(@intFromPtr(ptr1.?) % 8 == 0);

    const ptr2 = alocador.alocar(64, 16);
    try std.testing.expect(ptr2 != null);
    try std.testing.expect(@intFromPtr(ptr2.?) % 16 == 0);
}

Casos de uso comuns

  1. Alocadores de memória personalizados: Calcular alinhamentos, offsets e tamanhos de blocos alocados.
  2. Depuração de memória: Imprimir endereços de ponteiros para investigar layout de memória.
  3. Verificação de alinhamento: Verificar se um ponteiro está corretamente alinhado para operações SIMD ou requisitos de hardware.
  4. Desenvolvimento de kernel/drivers: Trabalhar com endereços de memória mapeados em hardware.
  5. Hashing de ponteiros: Usar o endereço como chave em tabelas hash.

Builtins relacionados

  • @ptrFromInt — Operação inversa: converte inteiro para ponteiro
  • @ptrCast — Conversão entre tipos de ponteiro
  • @alignCast — Converte alinhamento de ponteiro
  • @alignOf — Obtém o alinhamento de um tipo
  • @sizeOf — Obtém o tamanho em bytes de um tipo

Tutoriais relacionados

Continue aprendendo Zig

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