Zig Structs and Enums

In the Zig programming language, structs and enums are two fundamental data types.

Structs and enums are two main ways to define and use custom data types.

Structs and enums provide a higher level of data organization and type safety, suitable for different programming scenarios.

  • Struct: Used to combine related variables into a composite data type. Structs can contain fields and methods, suitable for organizing complex data.
  • Enum: Used to define a set of named constants, which can be enums without values or with values. Enums are suitable for representing a finite set of discrete values.

Struct

A struct is a composite data type that allows combining multiple data items of different types into a single type.

The syntax for structs in Zig is as follows:

const structName = struct {
    field1: FieldType1,
    field2: FieldType2,
    // 其他字段
};

In the following code, MyStruct is a struct type with three fields: field1 is a 32-bit integer, field2 is a double-precision floating-point number, and field3 is a pointer to a byte array.

struct MyStruct {
    field1: i32,
    field2: f64,
    field3: []const u8,
}

Example

const std = @import("std");

// Define a struct
const Person = struct {
    name: []const u8,
    age: u32,
};

pub fn main() void {
    // Create a struct instance
    const person = Person{
        .name = "Alice",
        .age = 30,
    };

    // Access struct fields and format correctly
    std.debug.print("Name: {s}\n", .{person.name}); // Use {s} to format slices
    std.debug.print("Age: {}\n", .{person.age});
}

Compile and run the above code, the output is:

Name: Alice
Age: 30

To modify fields in a struct, make sure you use var to define the struct instance so that you can modify field values. If you use const to define a struct instance, you cannot modify its field values.

Example

const std = @import("std");

// Define a struct
const Person = struct {
    name: []const u8,
    age: u32,
};

pub fn main() void {
    // Create a struct instance
    var person = Person{
        .name = "Alice",
        .age = 30,
    };

    // Output the initial values
    std.debug.print("Initial Name: {s}\n", .{person.name});
    std.debug.print("Initial Age: {}\n", .{person.age});

    // Modify the values of struct fields
    person.name = "Bob";
    person.age = 35;

    // Output the modified values
    std.debug.print("Modified Name: {s}\n", .{person.name});
    std.debug.print("Modified Age: {}\n", .{person.age});
}

Compile and run the above code, the output is:

Initial Name: Alice
Initial Age: 30
Modified Name: Bob
Modified Age: 35

Methods

In Zig, struct methods are defined using the fn keyword, similar to class methods in other programming languages.

Example

const std = @import("std");

const Rectangle = struct {
    width: u32,
    height: u32,

    // Method to calculate the area
    fn area(self: Rectangle) u32 {
        return self.width * self.height;
    }
};

pub fn main() void {
    var rect = Rectangle{
        .width = 10,
        .height = 5,
    };

    // Call the struct method
    std.debug.print("Area: {}\n", .{rect.area()});
}

Compile and run the above code, the output is:

Area: 50

Enum

An enum is a data type that consists of a fixed set of constant values.

The syntax for enums in Zig is as follows:

const enumName = enum {
    Variant1,
    Variant2,
    // 其他变体
};

In the following code, MyEnum is an enum type with three possible values: Option1, Option2, and Option3.

enum MyEnum {
    Option1,
    Option2,
    Option3,
}

Example

const std = @import("std");

// Define an enum
const Color = enum {
    Red,
    Green,
    Blue,
};

pub fn main() void {
    // Use the enum
    const favoriteColor = Color.Green;

    switch (favoriteColor) {
        Color.Red => std.debug.print("Red\n", .{}),
        Color.Green => std.debug.print("Green\n", .{}),
        Color.Blue => std.debug.print("Blue\n", .{}),
    }
}

Compile and run the above code, the output is:

Green

Enums with Values

Zig allows specifying specific values for each variant of an enum, which can be used to represent more information or for comparison.

Example

const std = @import("std");

// Define an enum with values
const Status = enum(u32) {
    Pending = 1,
    InProgress = 2,
    Completed = 3,
};

pub fn main() void {
    const taskStatus = Status.InProgress;

    switch (taskStatus) {
        Status.Pending => std.debug.print("Pending\n", .{}),
        Status.InProgress => std.debug.print("InProgress\n", .{}),
        Status.Completed => std.debug.print("Completed\n", .{}),
    }
}

Compile and run the above code, the output is:

InProgress

Using Enums as Fields

Enums can be used as struct fields, making structs more flexible and powerful.

Example

const std = @import("std");

const Status = enum {
    Active,
    Inactive,
    Suspended,
};

const User = struct {
    name: []const u8,
    status: Status,
};

pub fn main() void {
    // Create a User instance
    const user = User{
        .name = "Alice",
        .status = Status.Active,
    };

    // Output User's name field
    std.debug.print("User: {s}\n", .{user.name}); // Use {s} to format slices

    // Use a switch statement to output different states based on status
    switch (user.status) {
        Status.Active => std.debug.print("Status: Active\n", .{}),
        Status.Inactive => std.debug.print("Status: Inactive\n", .{}),
        Status.Suspended => std.debug.print("Status: Suspended\n", .{}),
    }
}

Compile and run the above code, the output is:

User: Alice
Status: Active
Other Extensions