Strugulling with bytesAsSlice behavior

Hello!

I am really new to zig, but so far language feels interesting.

In project I am using for learning zig I faced problem I don’t really know how to solve.

Basically, I have an array of some structs and I want to access raw bytes of it. Struct is packed, so such operation should not cause any problems, since every single byte of the array is meaningful.

To be more specific, I want smth like following

struct test {
    uint8_t a;
    uint8_t b;
    uint8_t c;
    uint8_t d;
};
struct test array[40];

((uint8_t *)array)[159] = 0x10;

I found that zig has std.mem.bytesAsSlice() function, but seems like it does not work the way I think. When I do

const Something = struct {
    val: u8,
    val1: u8,
    val2: u8,
    val3: u8,
};
var tst = std.mem.zeroes([40]Something);
var slice = std.mem.bytesAsSlice(u8, &tst); 

slice is an slice with length 40, rather than 160. Am I using an API wrong? Maybe there is another one? I’d really appreciate any help

Thanks!

Example:

Ok, I guess I found a solution in stdlib – sliceAsBytes. Sorry =)

2 Likes

You can also use @ptrCast in 0.14.0.

1 Like

Thanks for the tip!

You’ll want to make Something be an extern struct so that it has well-defined memory layout, then you can do @ptrCast((&tst)[0..1]).

Breaking that down:

  1. &tst - convert Something to *Something
  2. [0..1] - convert *Something to *[1]Something
  3. @ptrCast() - convert *[1]Something to []const u8

You’ll need to give slice a type to make this work.

7 Likes

You’ll want to make Something be an extern struct so that it has well-defined memory layout,

In my original code I use packed. Does it force C ABI for structs (+ removes padding)?

Not exactly. To force C ABI, you want extern struct. To remove padding, you need to add explicit align(1) to fields:

extern struct { 
  small: u8, 
  big: u64 align(1)
} 

packed struct is different. It is a bitfield. That is, a packed struct is an integer in a fancy hat. It is much closer to Erlang BitSyntax than to packed from C.

5 Likes

Thanks!

So bitfields work the same way as in C, i.e. order of fields may be arbitrary?

And thanks for detailed answer!

Very much not so. A packed struct is laid out from least to most significant byte, with no padding.

1 Like

Thanks y’all for detailed explanations!
Everything is now clear

1 Like