Skip to content

allow align(0) on struct fields #3802

Closed

Description

@andrewrk

This is a sister issue to #3133. Packed structs offer a way to explicitly provide the layout of a struct in memory. But non-packed structs also can offer something powerful: the ability to say that you do not need a field to be aligned to a byte boundary.

const S = struct {
    a: bool align(0),
    b: u8,
    c: bool align(0),
    d: bool align(0),
    e: bool align(0),
};

Because structs do not guarantee field order, Zig is allowed to put a, c, d, and e fields into 1 byte, making the entire struct only 2 bytes, rather than 5.

The compromise here is that pointers to align(0) fields have pointer metadata in the type that prevents it from being coerced to a "normal" pointer for that type. This the same thing as taking a pointer of a non-byte-aligned packed struct field.

However this would be quite useful for flags, where one typically does not need a pointer to an individual flag. Rather, one typically accesses flags from a base pointer, which would work just fine with align(0) flag fields.

Activity

  1. added
    proposalThis issue suggests language modifications. If it also has the "accepted" label then it is planned.
    on Nov 29, 2019
  2. added this to the 0.7.0 milestone on Nov 29, 2019
  3. JesseRMeyer commented on Nov 29, 2019

    @JesseRMeyer

    Is there a reason why someone wouldn't first reach for embedding a packed struct inside a normal struct for bitflags before trying this? I do see the general appeal of making align(0) well defined, an in the manner you've described, but specifically for flags, there are already, seemingly simpler, more controlled ways of accomplishing the task. Overall, I think that when operating at the bit level, one's mind is probably wanting data laid out carefully rather than letting the compiler take the wheel.

  4. andrewrk commented on Nov 29, 2019

    @andrewrk
    MemberAuthor

    A packed struct has a well-defined in-memory layout. If you do not need this, then it is better to avoid it, for plenty of reasons:

    • Zig is allowed to re-order fields for performance (e.g. profile-guided optimization), better memory usage, or safety reasons
    • Zig is allowed to insert an additional field for safety purposes, or padding for hot code swapping (hot code swapping #68) or incremental compilation
    • Type safety for @ptrCast and other related functions is possible (not implemented yet) when the type has no well-defined in-memory layout
    • Detection of undefined values is possible (not implemented yet) when the type has no well-defined in-memory layout

    However if you need well-defined in-memory layout, that's fine, that's what packed structs are for.

  5. daurnimator commented on Dec 22, 2019

    @daurnimator
    Contributor

    Shouldn't align(0) work on types in the general case? e.g. [1024] align(0) bool for a packed array of booleans

  6. modified the milestones: 0.7.0, 0.8.0 on Oct 9, 2020
  7. modified the milestones: 0.8.0, 0.9.0 on May 19, 2021
  8. modified the milestones: 0.9.0, 0.10.0 on Nov 20, 2021
  9. andrewrk commented on Jan 14, 2022

    @andrewrk
    MemberAuthor

    Rejected in favor of #5049 and #10113.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalThis issue suggests language modifications. If it also has the "accepted" label then it is planned.

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions