BitmapHeader struct size riddle

Why is the size of this struct 56 in Zig? It should be 54.

const BitmapHeader = extern struct
{
    signature: u16, // 2
    filesize: u32, // 6
    reserved: u32, // 10
    data_offset: u32, // 14
    header_size: u32, // 18
    width: i32, // 22
    height: i32, // 26
    planes: u16, // 28
    bits_per_pixel: u16, // 30
    compression: u32, // 34
    image_size: u32, // 38
    x_pixels_per_meter: i32, // 42
    y_pixels_per_meter: i32, // 46
    colors_used: u32, // 50
    colors_important: u32, // 54
};

extern defines the memory layout according to the C ABI: Documentation - The Zig Programming Language. The C implementation may introduce padding after/between fields for alignment reasons.

If you use packed struct, you’ll get 0 padding between fields, but that doesn’t mean an exact sizeOf: Inconsistent sizeOf vs bitSizeOf

3 Likes

Yes it is the padding!
But the layout of the struct is not garantueed to be in declaration order.
That is why I used extern.
After adding align(1) to the fields it was correct.

packed structs do have guaranteed declaration order: Documentation - The Zig Programming Language.

Packed struct is likely incorrect for this use case since you don’t want the backing integer to be a u448. extern struct with overridden alignment on a per-field basis is the right approach here.

3 Likes

@andrewrk
I remembered browsing through a Tetris game and looked there!