Open kj4tmp opened 1 month ago
Not sure how complete documentation is (I assume you mean langref).
In status-quo, a packed struct
is treated as a single integer that concatenates its fields' bits starting from the lowest-value bit.
So packed struct {a: A, b: B}
stores a: A
in its lowest-value bits and b: B
its highest-value bits.
Endianness affects the mapping of lower-value-byte vs higher-value-byte to lower-address-byte vs higher-address byte. So differences will be observable in the addresses of the constituent bytes.
If the packed struct
fits into one byte, there is no difference. If the packed struct
has more than 8 bits, its backing bytes will be exactly flipped in address layout, while the backing integer value will still be the same (in the respective native endianness). (Note: Backing bytes may be ceiled, f.e. @sizeOf(u24)
may be 4
, meaning the u24
is represented as 4 bytes in memory.)
probably also worth mentioning that padding bytes are added for allignment of packed structs, for example this assertion fails:
const EthernetHeader = packed struct(u112) {
dest_mac: u48,
src_mac: u48,
ether_type: u16,
comptime {
std.debug.assert(@sizeOf(@This()) == 112 / 8);
}
};
Zig Version
0.14.0-dev.66+1fdf13a14
Steps to Reproduce and Observed Behavior
The docs say packed structs have defined in-memory layout but do not fully describe what that in-memory layout is, especially when considering host endianness, non-byte aligned, and not-byte-width fields.
Expected Behavior
I expected the docs to describe the in-memory layout of structs under the effects of host-endianness, non-byte aligned, and not-byte-width fields.