I am struggling to find a way in zig to represent packed struct in C, tried packed struct and extern struct, both don’t seem to fit, i.e. the size of both are not exactly the sum of all fields in it. any hints would be appreciated.
Packed Zig struct is a concept that differs from __attribute__((packed))
. I think there’s no direct equivalent, but you can achieve same result like this:
struct __attribute__((packed)) foo
{
char a;
int c;
char b;
};
becomes
const foo = extern struct {
a: u8 align(1),
c: c_int align(1),
b: u8 align(1),
};
With alignment of 1
there would be no padding bytes between fields. You can also utilize translate-c
feature to construct struct definitions like this from their C counterpart.
Side question, why would you want this?
Welcome to Ziggit btw
That does the trick, Thanks a lot! I am writing a toy OS (mainly to learn zig ), some hardware defined structs could only be represented like that, that’s why I need it.
I’m curious which registers. The only ones that immediately come to mind on x86(_64) are the GDTR/IDTR which are a 2-byte limit and 4- (or 8) byte offset.
it’s tss, zig packed struct works for gdtr/idtr, at least in my case.
Welcome to Ziggit @voidpx!
This needs a bit of a warning: Zig structs have no defined layout. Using align(1)
will give you no padding within the struct, but the compiler reserves the right to put the fields in any order it would like to.
It sounds like you have hardware defined memory regions which don’t follow the default C layout (so you can’t use extern
). Your best bet is probably going to be a packed struct
in this case: even though it isn’t the same thing as __attribute__((packed))
, it does get you bit-for-bit control over the semantics of a region of memory.
If you have a C definition of the structure of interest, you can post it, that would help us help you translate it into Zig.
Thanks. I could workaround it with packed struct
, just with some bytes at the end wasted as @sizeOf
it is more than actually needed. it’s the tss struct Task State Segment - OSDev Wiki, if I just left it with all fields as u32, it wouldn’t have been a problem, but I preferred to access sp0 as u64 instead of handling low & high 32 bits separately, thus came the alignment problem.
thats because zig’s packed struct
is literally just an integer for bit fields, so it has to round up to the nearest valid integer size.
packed struct
is only appropriate if you want the ABI of the backing integer. Likely the best pattern here will be extern struct
compared with align(1)
on each field, exactly as @yataro showed above.
Or, depending on the situation, default alignment can be used, and only the specific unaligned pointer can be marked align(1)
. This would be the case if for example the struct is normally aligned, but for whatever reason it is being read from a byte buffer.
I actually missed that the example was extern
(hence the part about undefined layout), and didn’t even realize that align
worked with extern structs.
It would be nice to know more about the ABI of wide integers, as compared to structs of the same byte length. Is there any issue or writeup on that I could look into?