Tag type (bit size) of std.mem.Alignment

Hello! I’m new to Zig. I’m reading some parts of the standard library, and I came across the definition of Alignment.

/// Stored as a power-of-two.
pub const Alignment = enum(math.Log2Int(usize)) {
    @"1" = 0,
    @"2" = 1,
    @"4" = 2,
    @"8" = 3,
    @"16" = 4,
    @"32" = 5,
    @"64" = 6,
    _,
   // <truncated>
}

The enum uses a tag type defined by math.Log2Int(uszie) which on my machine resolves to u6, given usize is 64 bits for me.

I can understand that we’re trying to use a small unsigned integer, but why 6 bits? The values stored seem to go from 0 to 6 included. Wouldn’t 3 bits be enough?

I’m surely missing something related to the design of this struct.

Any explanation on this would be greatly appreciated. :smiley:

Only the values with explicit names (such as @"64") go from 0 to 6, but there are more. The underscore in the enum means that other values representable in u6 are also valid – just not named explicitly. For example @as(Alignment, @enumFromInt(63)) is valid, it just doesn’t have a name (which would be @"9223372036854775808")

1 Like

Thank you! The syntax to build an enum outside of the named values is interesting to see.

I think the core aspect of my question was more about: why would one want an alignment beyond 64? But I figured that pointers use usize to store their addresses. It thus follows that we want to be able to to say how many trailing zeros we would like to have for pointers, which is our alignment, and this cannot be bigger than the number of bits in a usize.

This number turns out to be 64 on my machine, and thus I need at least a u6 to store that value. On a 32 bits machine, a u5 would suffice, even though the normal max alignment would probably be 32 bits - 4 bytes, with the enum Alignment value being 2, that is 2 trailing zeroes for aligned pointers.

I think the max alignment depends on the context where alignment is used, if you create some sort of special allocator that gets huge chunks of memory it may want to use alignments that aren’t even guaranteed at lower levels, for example it could manage a mapping from virtual to physical memory, where the virtual has a big alignment and is one giant thing, but then maps that to smaller physical pages.

So while big alignments aren’t seen that often, there may be valid use-cases that can make use of these bigger alignments. (maybe to save a few critical bits to make some technique work etc.)

3 Likes