Manual Indexing into an Allocation

So, I added a basic example to show the concept, but my desire is to store data into a u8 buffer. No need for sentinels or anything as things are fixed length.

However, when I try to memcpy data over, it errors on

error: type '*u8' is not an indexable pointer
        @memcpy(&storage[i], &examples[i]);

which is just a bit surprising for me. In a sort of C sense, I would’ve expected this to work. copying the number of bytes available in the source to the dest, only encountering errors if the source exceeded the dest in length.

const std = @import("std");

pub fn main() !void {
    const GPA = std.heap.GeneralPurposeAllocator(.{});
    var gpa: GPA = .init;
    var allocator = gpa.allocator();
    const storage = try allocator.alloc(u8, 10);
    defer allocator.free(storage);
    @memset(storage, 0);

    const examples: [5][]const u8 = .{
        "aa",
        "bb",
        "cc",
        "dd",
        "ee",
    };

    var i: usize = 0;
    while (i < examples.len): (i += 1) {
        @memcpy(&storage[2 * i], &examples[i]);
    }
    std.debug.print("{s}\n", .{storage});


}

This change should work as expected:

@memcpy(storage[2 * i..].ptr, examples[i]);
zig build run
aabbccddee

From the language reference on memcpy:

dest must be a mutable slice, a mutable pointer to an array, or a mutable many-item pointer

source must be a slice, a pointer to an array, or a many-item pointer

… at least one of source and dest must provide a length, and if two lengths are provided, they must be equal

Your example’s mistakes are that dest is a single-item pointer, and that src is a pointer to a slice, not the slice itself.

In my example (noting there are many other ways to make it work), dest provides a many-item pointer to the target destination, and source is a slice containing the length so that memcpy knows how many items need to be copied.


Edit: fix some URLs

2 Likes

Applying your concept of .ptr instead of & worked for my more complex example, i.e. my actual problem.

1 Like