Saltar al contenido

09 · Estructuras de Datos

Layout de Memoria

`@repr`, `@align` y `@size` para control de layout en FFI y GPU.

En esta página

Por defecto, el compilador de Zolo puede reordenar los campos de un struct (@repr(zolo)) para optimización interna. Cuando el orden y el alineamiento de los campos son contratos — FFI con C/Rust, uniform buffers de GPU, protocolos binarios — declaras el layout explícitamente con atributos:

@repr(C), @repr(packed), @repr(transparent), @align(N) y @size(N).

13-repr-align-size.zolo
Playground
// Feature: `@repr` / `@align` / `@size` — struct layout control
// Syntax:
//   @repr(C | packed | transparent | zolo)   on the struct
//   @align(N)   on a field (N must be a power of two)
//   @size(N)    on a field (forces minimum byte size)
// When to use: FFI with C/Rust plugins, GPU uniform buffers, binary
//   protocols, layout-sensitive newtypes. Default `@repr(zolo)` lets
//   the compiler reorder fields, which is unsuitable for binary stability.
//
// See `specs/repr-align-size.md` for the full specification.

// 1. @repr(C) — fields kept in declaration order, C-compatible layout.
@repr(C)
struct PacketHeader {
    version: int,
    flags: int,
    length: int,
    seq: int,
}

let hdr = PacketHeader { version: 1, flags: 0, length: 256, seq: 42 }
print("hdr.seq = {hdr.seq}")

// 2. @repr(packed) — no padding between fields.
//    Useful for wire protocols where every byte matters.
@repr(packed)
struct WireFrame {
    magic: int,
    payload: int,
}

let w = WireFrame { magic: 0xCAFE, payload: 100 }
print("w.magic = {w.magic}")

// 3. @repr(transparent) — single-field newtype-like with identical
//    binary layout to its inner field.
@repr(transparent)
struct Handle {
    raw: int,
}

let h = Handle { raw: 42 }
print("h.raw = {h.raw}")

// 4. @align(N) on a field — force alignment under @repr(C).
//    Useful for GPU uniform buffers where vec3 must be 16-byte aligned.
@repr(C)
struct CameraUniform {
    @align(16) view_proj: float,
    @align(16) view_pos:  float,
    @align(16) time:      float,
}

let cam = CameraUniform { view_proj: 1.0, view_pos: 0.0, time: 0.5 }
print("cam.time = {cam.time}")

// 5. @size(N) on a field — pad to a minimum byte size.
@repr(C)
struct PaddedHeader {
    @size(64) header: int,
    payload: int,
}

let p = PaddedHeader { header: 1, payload: 2 }
print("p.payload = {p.payload}")

// 6. Errors caught at lint/check time (uncomment to see):
//
//   @repr(unknown_policy)
//   struct X { x: int }
//     warning[unknown-repr]: unknown @repr policy `unknown_policy`
//
//   @repr(transparent)
//   struct Two { a: int, b: int }
//     error[transparent-multi-field]: @repr(transparent) requires exactly one field
//
//   @repr(C)
//   struct Bad {
//       @align(3) x: int     // not a power of two
//       @align(8192) y: int  // exceeds 4096
//   }
//     error[align-not-power-of-two]
//     error[align-too-large]
//
//   struct DefaultRepr {
//       @align(8) x: int   // @align without @repr — meaningless
//   }
//     error[layout-in-default-repr]: `@align` requires an explicit
//                                    `@repr(C|packed|transparent)` on the struct

Referencia rápida:

  • @repr(C) — campos en orden de declaración, compatible con C.
  • @repr(packed) — sin padding entre campos (protocolo de red, archivo binario).
  • @repr(transparent) — requiere exactamente un campo; layout idéntico al tipo interno.
  • @align(N) — en un campo, fuerza el alineamiento a N bytes (potencia de dos, máx. 4096).
  • @size(N) — en un campo, garantiza un tamaño mínimo de N bytes.

@align y @size requieren que el struct tenga un @repr explícito (no zolo). El compilador emite un error en tiempo de verificación si la combinación es inválida.

Consulta también

Índice global

Encuentra tu camino por Zolo

Prueba una idea

Empieza aquí

9 resultados

9 resultados

enespt-br