Search code examples
stringzig

how to deal with Zig struct strings with variable size


I have the following

const Task = struct {
    id: u32,
    name: [34]u8,
    progress: u8,
};

but for the Task.name declaration I have a probblem which is the length of the name

I could declare it as

name: [34:0]u8, but how to init it?

or

name: [34:0]u8 = undefined, is there a memcpy() equivalent in Zig?

or just

name: [34]u8 = undefined,this only accepts 34 bytes long names

so, what is the best way (I don't have much experience with dynamic memory)


Solution

  • Assuming that the name field is supposed to be a string, ordinarily in Zig you would use a slice of const u8 for strings. You can then use string literals or dynamically build strings as you wish using arrays or allocators for storage. Something like this:

    const std = @import("std");
    const print = std.debug.print;
    
    const Task = struct {
        id: u32,
        name: []const u8,
        progress: u8,
    };
    
    pub fn main() void {
        const my_task = Task{
            .id = 42,
            .name = "Ultimate Answer",
            .progress = 0,
        };
    
        print("On the question of \"{s}\"...\n", .{my_task.name});
        print("Universe: {}\n", .{my_task.id});
        print("Humanity: {}\n", .{my_task.progress});
    
        var another_task = Task{
            .id = 21,
            .name = "",
            .progress = 0,
        };
    
        print("another_task.name ({s})\n", .{another_task.name});
    
        another_task.name = "Halfway There!";
        print("another_task.name ({s})\n", .{another_task.name});
    
        var build_arr = [_]u8{ 'D', 'y', 'n', 'a', 'm', 'i', 'c', '.' };
        build_arr[build_arr.len - 1] = '!';
        another_task.name = build_arr[0..];
        print("another_task.name ({s})\n", .{another_task.name});
    }
    
    > zig build-exe .\task.zig
    > .\task.exe
    On the question of "Ultimate Answer"...
    Universe: 42
    Humanity: 0
    another_task.name ()
    another_task.name (Halfway There!)
    another_task.name (Dynamic!)
    

    Regarding memcpy, Zig has the built in @memcpy, as well as std.mem.copyForwards and std.mem.copyBackwards in the Standard Library. When and how these would be used depends on more specific details about exactly what OP hopes to accomplish.

    As a general rule, one should probably try to use slices as in the example code above.