#Casting [n]u8 to []u8

1 messages · Page 1 of 1 (latest)

quiet steeple
#

I'm learning Zig and having trouble with the simplest of things. I can't figure how to make a field to hold an array...

const std = @import("std");
const DEFAULT_BUF_SIZE: usize = 4096;

pub const Buffer = struct {
    content: []u8,

    pub fn makeBuffer(comptime size: usize) Buffer {
        return .{ .content = std.mem.zeroes([size]u8)[0..] };
    }

    pub fn makeDefaultBuffer() Buffer {
        return makeBuffer(DEFAULT_BUF_SIZE);
    }
};

If I call Buffer.makeDefaultBuffer(), I get this error:

error: expected type '[]u8', found '*const [4096]u8'
        return .{ .content = std.mem.zeroes([size]u8)[0..] };
pine yarrow
#

The reason for the error is that std.mem.zeros([size]u8)[0..] is producing a const slice, but you're trying to store it in a field of type []u8, which is mutable. In this case, what you're trying to do won't work, because the array produced by std.mem.zeroes would go out of scope after makeBuffer returns, and so the content slice would be pointing to invalid memory.

There are two approaches you could take to fix this: one is to use an allocator in makeBuffer to dynamically allocate a buffer of the requested size, and then make sure you free it when you're done with Buffer, and another (since you're using a comptime size) is to make the Buffer type parameterizable and store an array rather than a slice:

pub fn Buffer(comptime size: usize) type {
    return struct {
        content: [size]u8,
    }
}
#

A type like []u8 is a slice, while [size]u8 is an array: slices are actually just pointers (with an associated length), so they can't be used without something else backing the thing they're pointing to