How to memcopy a many pointer

Hey trying to learn how to use many pointers. I don’t really understand how to do memcopy.
making a REPL

var inputBuf: [1024]u8 = undefined;
const input = (try stdin.readUntilDelimiterOrEof(inputBuf[0..], '\n')) orelse {
            try stdout.print("\n", .{});
            return;
};
var args: [maxArgs]?[*:0]u8 = undefined;
var argv = std.mem.split(u8, input, " ");
var i: usize = 0;
while (argv.next()) |arg| {
            std.mem.copyForwards(?*u8, &args[i], arg);
            //@memcpy(&args[i], arg);
            args[i][arg.len] = 0; // add sentinel
           i += 1;
}

tried:

error: expected type '[]u8', found '*?[*:0]u8'                                                                                                                    std.mem.copyForwards(u8, &args[i], arg);

main.zig:31:40: error: expected type '[]?*u8', found '*?[*:0]u8'                                                                                                                  std.mem.copyForwards(?*u8, &args[i], arg); 

main.zig:32:25: error: type '?[*:0]u8' is not an indexable pointer                                                                                                                @memcpy(args[i], arg);                                                                                                                                                        ~~~~^~~                                                                                                                                           main.zig:32:25: note: operand must be a slice, a many pointer or a pointer to an array   

What am I missing here I thought args is a many pointer. If not how would I copy it to this variable?

Both copyForwards and @memcpy expect slices (pointer to many items and length).
Your second argument is a slice, but the first argument is a pointer.
see: Convert between pointers and slices


var args: [maxArgs]?[*:0]u8 = undefined;

args allocates an array of maxArgs slices, but does not allocate storage for the actual bytes that these slices point to.

For your use case you need to both allocate enough memory and copy the contents.
There is a function for this in allocator called dupe and if you want to copy zero terminated strings dupeZ.

dupe source code allocates memory (the allocator returns a slice) and then uses @memcpy to copy its contents.

1 Like

How would I actually go about copying?
this compiles:

            const cpyArg = try std.mem.Allocator.dupe(allocator, u8, arg);

I try to copy it to args like I was trying to do before:

            std.mem.copyForwards(?*u8, &args[i], arg);

get this error:

main.zig:30:40: error: expected type '[]?*u8', found '*?[*:0]u8'
            std.mem.copyForwards(?*u8, &args[i], cpyArg);

try to assign it instead:

main.zig:32:23: error: expected type '?[*:0]u8', found '*u8'
            args[i] = &cpyArg[i];
                      ^~~~~~~~~~
main.zig:32:23: note: a single pointer cannot cast into a many pointer

args does not have a buffer to hold the string. There is no meaning to copy bytes because there is no destination buffer.

args[i] = cpyArg; is the correct way to transfer the slice to data, but you have to declare args as an array of slices to u8 var args: [maxArgs][]u8 = undefined;


If you want to have zero terminated strings, you can leave the args declarations as is, call dupeZ instead, and simply copy the zero terminated pointer of the slice args[i] = cpyArg.ptr;

const cpyArg = try std.mem.Allocator.dupeZ(allocator, u8, arg);
args[i] = cpyArg.ptr;

Note to use the same allocator to free the dupeZ allocated strings (each args[i]).


What the compiler says about this:

cpyArg[i] is the i element of cpyArg, its type is u8, then you get the address of &cpyArg[i] that means you now have a pointer to a single u8 (the ith) and its type is *u8.
The compiler of course don’t know how to assign a pointer to a character to ?[*:0]u8 that is an optional slice (pointer and length) where the pointer pointes to zero terminated u8.

1 Like

This works! Thank you for the quick replies! I’ve done some small projects in Zig but this is the first one where I’m trying to do system programming level stuff.