Zig 提供了强大的结构体(Struct)和枚举(Enum)机制,允许开发者创建更复杂的自定义数据类型。在 Zig 中,结构体和枚举是进行数据建模和类型安全的基本工具,支持不同的类型组合和灵活的数据结构。本文将详细介绍 Zig 中的结构体和枚举,并配以示例代码。


📖 目录

  1. 结构体基础
  2. 结构体操作
  3. 结构体方法
  4. 枚举基础
  5. 枚举操作
  6. 结构体与枚举结合
  7. 参考资料

1. 结构体基础

在 Zig 中,结构体(Struct)是 由多个字段组成的数据类型,可以包含不同类型的成员。每个字段都需要显式指定类型。

🔹 结构体定义

const std = @import("std");

const Point = struct {
    x: i32,
    y: i32,
};

pub fn main() void {
    const p = Point{ .x = 5, .y = 10 }; // 使用结构体字面量初始化
    std.debug.print("Point: ({}, {})\n", .{p.x, p.y}); // 输出: (5, 10)
}

  • struct:定义结构体类型。
  • Point{ .x = 5, .y = 10 }:初始化结构体实例,指定 xy 的值。

2. 结构体操作

🔹 访问结构体字段

pub fn main() void {
    const p = Point{ .x = 3, .y = 4 };
    
    std.debug.print("X: {}\n", .{p.x}); // 输出: X: 3
    std.debug.print("Y: {}\n", .{p.y}); // 输出: Y: 4
}

🔹 修改结构体字段

pub fn main() void {
    var p = Point{ .x = 1, .y = 2 };
    
    p.x = 10; // 修改字段值
    p.y = 20;
    
    std.debug.print("Updated Point: ({}, {})\n", .{p.x, p.y}); // 输出: (10, 20)
}


3. 结构体方法

Zig 支持给结构体定义 方法(函数),方法是绑定到结构体的函数,通常会在结构体中使用 self 参数来访问其成员。

🔹 结构体方法示例

const Point = struct {
    x: i32,
    y: i32,

    pub fn distance(self: *Point) f64 {
        return @sqrt(@intToFloat(f64, self.x * self.x + self.y * self.y));
    },
};

pub fn main() void {
    var p = Point{ .x = 3, .y = 4 };
    const dist = p.distance();
    std.debug.print("Distance from origin: {}\n", .{dist}); // 输出: 5.0
}

  • self: *Point:方法中的 self 指向当前结构体的实例。
  • p.distance():调用结构体的方法。

4. 枚举基础

Zig 枚举类似于其他语言中的枚举,但它没有自动赋值。Zig 允许为枚举成员指定明确的值。

🔹 枚举定义

const Color = enum {
    Red = 1,
    Green = 2,
    Blue = 3,
};

pub fn main() void {
    const c: Color = Color.Green;
    std.debug.print("Color value: {}\n", .{c}); // 输出: 2
}

  • enum:定义枚举类型。
  • Red = 1:为 Red 成员显式指定值为 1,其他成员依次递增。
  • const c: Color = Color.Green:将枚举成员 Green 赋值给变量 c

🔹 枚举的原始值

Zig 枚举的原始值可以通过 @intToEnum@enumToInt 来进行转换:

const Color = enum {
    Red = 1,
    Green = 2,
    Blue = 3,
};

pub fn main() void {
    const color_int = @enumToInt(Color.Green); // 获取枚举的原始整数值
    std.debug.print("Green as int: {}\n", .{color_int}); // 输出: 2
}


5. 枚举操作

🔹 使用枚举作为标志位

const Flag = enum {
    Read = 1,
    Write = 2,
    Execute = 4,
};

pub fn main() void {
    var permissions: u32 = Flag.Read | Flag.Write; // 按位或组合
    std.debug.print("Permissions: {}\n", .{permissions}); // 输出: 3 (Read + Write)
}

🔹 使用 switch 语句处理枚举

const Color = enum {
    Red,
    Green,
    Blue,
};

pub fn main() void {
    const c = Color.Green;
    switch (c) {
        Color.Red => std.debug.print("Red color\n", .{}),
        Color.Green => std.debug.print("Green color\n", .{}), // 输出: Green color
        Color.Blue => std.debug.print("Blue color\n", .{}),
    }
}

  • switch 语句根据枚举的值执行不同的分支。

6. 结构体与枚举结合

结构体和枚举可以结合使用,形成复杂的数据类型。

🔹 结构体包含枚举

const std = @import("std");

const Shape = enum {
    Circle,
    Square,
    Triangle,
};

const ColoredShape = struct {
    shape: Shape,
    color: []const u8,
};

pub fn main() void {
    const redCircle = ColoredShape{
        .shape = Shape.Circle,
        .color = "Red",
    };

    std.debug.print("Shape: {:?}, Color: {}\n", .{redCircle.shape, redCircle.color}); // 输出: Shape: Circle, Color: Red
}

  • ColoredShape 结构体包含了 Shape 枚举作为字段。

7. 参考资料