Packed vs extern structs

Recently I’ve been trying to generate data for R8G8B8 OpenGL texture in comptime, and found out that packed struct is not as packed as I initially assumed. Specifically, despite having no padding between structure fields, there’s padding at the end of the struct.

extern struct, on the other hand, is ‘fully packed’. Compare:

const ColrPacked = packed struct { r: u8, g: u8, b: u8 };
const packed_pixels: [128 * 128]ColrPacked = undefined;
const ColrExtern = extern struct { r: u8, g: u8, b: u8 };
const extern_pixels: [128 * 128]ColrExtern = undefined;
std.debug.print("@bitSizeOf(ColrPacked) = {}, @sizeOf(ColrPacked) = {}\n", .{@bitSizeOf(ColrPacked), @sizeOf(ColrPacked)});
std.debug.print("@sizeOf(packed_pixels) = {}\n\n", .{@sizeOf(@TypeOf(packed_pixels))});
std.debug.print("@bitSizeOf(ColrExtern) = {}, @sizeOf(ColrExtern) = {}\n", .{@bitSizeOf(ColrExtern), @sizeOf(ColrExtern)});
std.debug.print("@sizeOf(extern_pixels) = {}\n", .{@sizeOf(@TypeOf(extern_pixels))});

And the output is:

@bitSizeOf(ColrPacked) = 24, @sizeOf(ColrPacked) = 4
@sizeOf(packed_pixels) = 65536

@bitSizeOf(ColrExtern) = 24, @sizeOf(ColrExtern) = 3
@sizeOf(extern_pixels) = 49152

To be fair, documentation hints at this: There is no padding between fields.
Between fields, but not between instances of the struct.

But on the other hand, it warns against using extern struct for anything other than C interop: This kind of struct should only be used for compatibility with the C ABI. Every other use case should be solved with packed struct or normal struct.

So, of course, I could use something like const pixels: [128 * 128 * 3]u8, instead of extern struct { r: u8, g: u8, b: u8 }, but that’s just … awkward, innit?

I think this text is old, packed structs have been redesigned to be “fancy integers you can easily extract bit ranges from” and now extern structs are used for everything else.


Thanks. I take this as an official license to use extern struct wherever I need it then. :upside_down_face:
For example when I need a ‘truly packed’ struct type.

1 Like