Skip to main content

Structs

Structs are Zig's most common kind of composite data type, allowing you to define types that can store a fixed set of named fields. Zig gives no guarantees about the in-memory order of fields in a struct or its size. Like arrays, structs are also neatly constructed with T{} syntax. Here is an example of declaring and filling a struct.

const Vec3 = struct { x: f32, y: f32, z: f32 };

test "struct usage" {
const my_vector = Vec3{
.x = 0,
.y = 100,
.z = 50,
};
_ = my_vector;
}

Struct fields cannot be implicitly uninitialised:

test "missing struct field" {
const my_vector = Vec3{
.x = 0,
.z = 50,
};
_ = my_vector;
}
error: missing field: 'y'
const my_vector = Vec3{
^

Fields may be given defaults:

const Vec4 = struct { x: f32 = 0, y: f32 = 0, z: f32 = 0, w: f32 = 0 };

test "struct defaults" {
const my_vector = Vec4{
.x = 25,
.y = -50,
};
_ = my_vector;
}

Like enums, structs may also contain functions and declarations.

Structs have the unique property that when given a pointer to a struct, one level of dereferencing is done automatically when accessing fields. Notice how, in this example, self.x and self.y are accessed in the swap function without needing to dereference the self pointer.

const expect = @import("std").testing.expect;

const Stuff = struct {
x: i32,
y: i32,
fn swap(self: *Stuff) void {
const tmp = self.x;
self.x = self.y;
self.y = tmp;
}
};

test "automatic dereference" {
var thing = Stuff{ .x = 10, .y = 20 };
thing.swap();
try expect(thing.x == 20);
try expect(thing.y == 10);
}