#Change alignment and backing integer type of packed struct

1 messages Ā· Page 1 of 1 (latest)

stable basin
#

Can I change the alignment of a struct? I am trying to reinterpret some bytes I get as a struct

var buffer = [_]u8{0} ** 16;
_ = try std.os.read(fd, &buffer);

const response_header: *HciMessageHeader = @ptrCast(&buffer[0]);

And I have defined HciMessageHeader as

const HciMessageHeader align(1) = packed struct {
    op_code: u16,
    index: u16,
    len: u16,
};

Compiler tells me that HciMessageHeader has an alignment of 8. I thought I could change that with align(1) but it seems to have no effect. I also tried to set the alignment when defining the response_header variable that also had no effect.

Is it not possible to change the alignment of a packed struct?

Thanks

full crypt
#

Not sure if it's possible to change the alignment of a struct at the time of definition but you can definitely change the alignment of the pointer type: * align(1) MyType

stable basin
#

Ohh, now I see my error. I wrote *Type align(1)...

#

Would still be interested though if I can do that "by default" for a type

full crypt
#

I think it'ss possible by manually specifying the field alignments:

struct {
    a: u32 align(1),
    b: u32 align(1),
}

but the annoying part is having to specify the alignment for each individual field.

stable basin
#

That is unfortunately disallowed, but thanks for trying ;)

src/main.zig:4:24: error: unable to override alignment of packed struct fields
    op_code: u16 align(1),
stable basin
#

It is also very inconvenient that @sizeOf(HciMessageHeader) is now 8, because it really only needs 6 bytes to store itself. Is there a way to change the type of the backing integer to u6?

#

Change alignment and backing integer type of packed struct

#

Ok this is weird? I tried using packed struct(u48) but @sizeOf still reports a size of 8 bytes?

#

Okok that actually makes sense, I can use @bitSizeOf instead and divide the value by 8 to get the struct size in bytes šŸ‘

loud reef
#

you could get the size 6 w/ extern structs + field align(1).

const std = @import("std");

const HciMessageHeader = extern struct {
    op_code: u16 align(1),
    index: u16 align(1),
    len: u16 align(1),

    comptime {
        std.debug.assert(@sizeOf(HciMessageHeader) == 6);
    }
};

test {
    var buffer = [_]u8{0} ** 16;

    const response_header: *HciMessageHeader = @ptrCast(&buffer[3]);
    std.debug.print("response_header={}\n", .{response_header});
}
#

i think it might only actually be necessaary to align the last field in this case.

stable basin
#

thank you, I will give that a try šŸ‘

stable basin
#

I am honestly not sure which solution I prefer. Using a packed struct has the massive benefit that I can just be sure the alignment is the same as the C structs (which are marked with the packed attribute). On the other hand it means @sizeOf does not work - which is easy to work around but just odd. I think I will keep the packed structs for now and deal with defining a const SIZE for each struct which uses @bitSizeOf

loud reef
#

are you sure? i thought extern structs + align attributes are the equivalent of c structs + packed attrs

stable basin
#

well, it is just what packed does automatically, right?

#

(not sure myself)

loud reef
#

packed structs are just integers in disguise and behave in similarly.

#

so for example an i7 has bit size of 7 but size of 1

#

same thing with a packed struct of bit size 7

stable basin
#

hmm, I guess using extern then would be the lesser "I am abusing some random concept to make my use case work"?

loud reef
#

maybe. we use packed or extern structs when we need defined memory layouts. the main drawback of using custom aligned fields would be unaligned reads which can be slower sometimes

#

but i think on x86 they are ok

stable basin
#

I mean this all is basically premature optimization, I am trading unaligned reads for zero-copy reinterpretation of some bytes šŸ¤·ā€ā™‚ļø

#

But since the linux kernel has all those data structures packed they sure seem to think the memory reduction is worth it