Right, I’m asking why you want to know that information.
Here’s a more concrete example to illustrate what I mean:
const A = struct {
c: u16,
a: bool,
b: bool,
};
comptime {
@compileLog("A", @sizeOf(A), @bitOffsetOf(A, "a"), @bitOffsetOf(A, "b"), @bitOffsetOf(A, "c"));
}
const B = struct {
a: bool,
c: u16,
b: bool,
};
comptime {
@compileLog("B", @sizeOf(B), @bitOffsetOf(B, "a"), @bitOffsetOf(B, "b"), @bitOffsetOf(B, "c"));
}
const C = struct {
a: bool,
b: bool,
c: u16,
};
comptime {
@compileLog("C", @sizeOf(C), @bitOffsetOf(C, "a"), @bitOffsetOf(C, "b"), @bitOffsetOf(C, "c"));
}
When compiled, the compile logs will (currently) print:
@as(*const [1:0]u8, "A"), @as(comptime_int, 4), @as(comptime_int, 16), @as(comptime_int, 24), @as(comptime_int, 0)
@as(*const [1:0]u8, "B"), @as(comptime_int, 4), @as(comptime_int, 16), @as(comptime_int, 24), @as(comptime_int, 0)
@as(*const [1:0]u8, "C"), @as(comptime_int, 4), @as(comptime_int, 16), @as(comptime_int, 24), @as(comptime_int, 0)
That is, all 3 structs will have exactly the same layout (size of 4 bytes, fields ordered u16
, bool
, bool
), even though the fields are all ordered differently in the definitions. And the Zig compiler is free to change that ordering/size at any point. If you notice it doing something suboptimal, the way to go would be to file an issue so that it gets fixed in the compiler.
In other words, for a regular struct
in Zig, finding out what a struct’s size and padding are doesn’t really give you any actionable information. You’re only finding out what the compiler happens to be doing now, but that could always change. So, if you write any code that depends on a particular layout (like interoperating with C, or pointer casting between different structs, etc), then you are by definition writing buggy code when using a regular struct
, and you should instead be reaching for extern struct
(which guarantees a layout according to the C ABI) or packed struct
(where the size/padding is easy to discern).
All that said, tooling to provide size/alignment/padding/etc information without needing to use @compileLog
/etc would still be nice to have; this is just a caveat worth knowing.