Alignment (Alinhamento) em Zig — O que é e Como Usar

Alignment (Alinhamento) em Zig — O que é e Como Usar

Definição

Alignment (alinhamento) em Zig refere-se à restrição de que certos tipos de dados devem estar posicionados em endereços de memória que são múltiplos de um valor específico. Por exemplo, um u32 tipicamente requer alinhamento de 4 bytes — seu endereço deve ser divisível por 4.

O alinhamento existe porque processadores acessam memória de forma mais eficiente (e às vezes apenas) quando os dados estão alinhados corretamente. Zig expõe o controle de alinhamento diretamente no sistema de tipos.

Por que Alignment Importa

  1. Performance: Acesso alinhado é mais rápido; acesso não-alinhado pode custar 2x ou mais.
  2. Correção: Em algumas arquiteturas (ARM, RISC-V), acesso não-alinhado causa falha de hardware.
  3. SIMD/Vetores: Operações vetoriais exigem alinhamento específico (16, 32 ou 64 bytes).
  4. Interop com C: O ABI C define alinhamentos que Zig precisa respeitar em extern struct.

Exemplo Prático

Consultando Alinhamento

const std = @import("std");

pub fn main() void {
    std.debug.print("u8:  align = {}\n", .{@alignOf(u8)});   // 1
    std.debug.print("u16: align = {}\n", .{@alignOf(u16)});  // 2
    std.debug.print("u32: align = {}\n", .{@alignOf(u32)});  // 4
    std.debug.print("u64: align = {}\n", .{@alignOf(u64)});  // 8
    std.debug.print("f64: align = {}\n", .{@alignOf(f64)});  // 8
}

Ponteiros com Alinhamento Customizado

fn processarSIMD(dados: [*]align(16) const f32) void {
    // Dados garantidamente alinhados a 16 bytes
    // Operações SIMD seguras aqui
    _ = dados;
}

pub fn main() void {
    // Array com alinhamento customizado
    var buffer align(16) = [_]f32{ 1.0, 2.0, 3.0, 4.0 };
    processarSIMD(&buffer);
}

Alinhamento em Structs

const std = @import("std");

const SemPadding = extern struct {
    a: u32, // offset 0, align 4
    b: u32, // offset 4, align 4
    c: u32, // offset 8, align 4
};

const ComPadding = extern struct {
    a: u8,  // offset 0, align 1
    // 3 bytes de padding aqui!
    b: u32, // offset 4, align 4
    c: u8,  // offset 8, align 1
    // 3 bytes de padding aqui!
};

pub fn main() void {
    std.debug.print("SemPadding: {} bytes\n", .{@sizeOf(SemPadding)});  // 12
    std.debug.print("ComPadding: {} bytes\n", .{@sizeOf(ComPadding)});  // 12 (com padding!)

    // Reordenando para economizar:
    const Otimizado = extern struct {
        b: u32, // offset 0
        a: u8,  // offset 4
        c: u8,  // offset 5
        // 2 bytes de padding
    };
    std.debug.print("Otimizado: {} bytes\n", .{@sizeOf(Otimizado)});  // 8
}

@alignCast

fn processar(ptr: *align(1) u32) void {
    // ptr pode estar em qualquer endereço
    // Para operações que exigem alinhamento natural:
    const alinhado: *u32 = @alignCast(ptr);
    _ = alinhado;
}

Alocação com Alinhamento Específico

const std = @import("std");

pub fn main() !void {
    const allocator = std.heap.page_allocator;

    // Alocar com alinhamento customizado
    const dados = try allocator.alignedAlloc(f32, 32, 1024);
    defer allocator.free(dados);

    // dados está alinhado a 32 bytes — ideal para AVX
    std.debug.print("Endereço: {*}\n", .{dados.ptr});
}

Alinhamentos Comuns

TipoAlinhamento típico (x86_64)
u8, i81 byte
u16, i162 bytes
u32, i32, f324 bytes
u64, i64, f648 bytes
u128, i12816 bytes
SIMD @Vector(4, f32)16 bytes
Cache line64 bytes

Armadilhas Comuns

  • Ignorar alinhamento em interop C: Structs extern devem respeitar o alinhamento do ABI C. Use extern struct em vez de struct.
  • @alignCast inseguro: Se o ponteiro não estiver realmente alinhado, @alignCast causa comportamento indefinido em Release.
  • Padding desperdiça memória: Em arrays de structs com padding, o desperdício se multiplica. Reordene campos para minimizar padding.
  • Assumir alinhamento: Diferentes arquiteturas têm diferentes requisitos. Não assuma que funciona em x86 significa que funciona em ARM.

Termos Relacionados

Tutoriais Relacionados

Continue aprendendo Zig

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