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?
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.
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;
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.
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.