#Slice of Pointers in a Struct Field

1 messages · Page 1 of 1 (latest)

opaque torrent
#

I am new to Zig (and system languages in general outside of C in college). So excuse me if this is a B question for an A problem lol but I don't know any better.

I am looking to store a slice of struct pointers in a struct field, to make some shared behavoir a little easier for a little physics simulator.

const obj = motion.Motion1DOF.new_basic("MotionBoi", 1.0, 0.0, [_]*forces.Force{ &simple, &spring });
}

Here I try to intialize my struct using a method new_basic, wich has the following definition:

pub const Motion1DOF = struct {
    name: []const u8,
    max_pos: f64,
    min_pos: f64,
    pos: f64 = 0.0,
    vel: f64 = 0.0,
    accel: f64 = 0.0,
    net_force: f64 = 0.0,
    mass: f64 = 1.0,
    connections: []*forces.Force,

    pub fn new_basic(
        name: []const u8,
        max_pos: f64,
        min_pos: f64,
        connections: []*forces.Force,
    ) Motion1DOF {
        const new_motion = Motion1DOF{ .name = name, .max_pos = max_pos, .min_pos = min_pos, .connections = connections };

        // Init connections to ensure two way
        // Errors with this are handled a the connection level in init_connection
        for (connections) |connection| {
            connection.*.init_connection(new_motion);
        }

        return new_motion;
    }

Unfortunatly, I am unable to get success, and the compiler is telling me somthing that I am sure is very smart but I don't have the brain power to decode.

#
main.zig:10:84: error: array literal requires address-of operator (&) to coerce to slice type '[]*Physics.Forces.Force'
    const obj = motion.Motion1DOF.new_basic("MotionBoi", 1.0, 0.0, [_]*forces.Force{ &simple, &spring });
                                                                   ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
referenced by:
    posixCallMainAndExit: /home/sattva/Git/zig-linux-x86_64-0.14.0-dev.1472+3929cac15/lib/std/start.zig:615:37
    _start: /home/sattva/Git/zig-linux-x86_64-0.14.0-dev.1472+3929cac15/lib/std/start.zig:422:40
    comptime: /home/sattva/Git/zig-linux-x86_64-0.14.0-dev.1472+3929cac15/lib/std/start.zig:92:63
    start: /home/sattva/Git/zig-linux-x86_64-0.14.0-dev.1472+3929cac15/lib/std/std.zig:101:27
    comptime: /home/sattva/Git/zig-linux-x86_64-0.14.0-dev.1472+3929cac15/lib/std/std.zig:160:9

How can I properly intialize the array of pointers in this struct? The compiler wants me to point to get the address of this array (which I think makes sense) but doing so gives another error and I am a bit lost.

gentle yacht
#

the other error is because of constness

#

[]T is a mutable slice but taking a pointer to temporary values, e.g. an array literal, gives a const pointer/slice

#

if you need to modify the elements of connections then it has to exist mutably somewhere, either allocated or assigned to a var

opaque torrent
#

I do not wish to ever modify the elements of connections, they will remain constant for all runtime. Using []const *T is what I want for this application then!

Thanks!

opaque torrent
cyan topaz
#

When you create a temporary value like [_]*forces.Force{ &simple, &spring } Zig places this temporary value in the global constants section of the executable, which is write protected on most OSs. This means that this temporary value must be const. Attempting to modify a value in this section will typically result in a segmentation fault or equivalent error at runtime.

Conversion from an array to a slice is done by taking a pointer to the start of the array and bundling it with the length of the array. That's what a slice is, a pointer and a length. Constness carries through this conversion though, so if the original array was const, the resulting slice must also be const. It is possible to explicitly remove constness through the @constCast() intrinsic, but this is almost always a bad idea (there are legitimate uses, but they are few and far between).

For example: https://godbolt.org/z/68E46MP6v here I create a constant called str of type *const [5:0]u8, read as "a pointer to a 5 element null terminated array of u8s" , convert that to a non-const slice of u8 by using @constCast() to remove the const qualification, and then attempt to edit the value changing the h in hello to an e, which blows up, because you're not allowed to modify global program constants. This is no different than creating a temporary value and attempting to modify it.

Hopefully this is enough to fully explain things.