在 Zig 语言中,数组(Array) 是一种固定大小的序列,而 切片(Slice) 是数组的动态视图,提供更灵活的操作方式。Zig 通过严格的类型系统确保数组和切片的安全性,并提供了强大的 指针、索引、迭代 和 内存管理 机制。本文将详细介绍 Zig 中的数组和切片,并配以示例代码。
📖 目录
1. 数组基础
Zig 数组的大小 在编译时固定,数组的元素类型必须一致。
🔹 数组的声明
const arr: [5]i32 = [5]i32{1, 2, 3, 4, 5};
[5]i32
:表示数组包含 5 个i32
类型的元素。{1, 2, 3, 4, 5}
:数组的初始化值。
🔹 访问数组元素
const std = @import("std");
pub fn main() void {
const arr: [3]i32 = [3]i32{10, 20, 30};
std.debug.print("第一个元素: {}\n", .{arr[0]}); // 10
std.debug.print("最后一个元素: {}\n", .{arr[2]}); // 30
}
⚠ 注意:访问超出范围的索引会导致 编译错误 或 运行时错误(如果开启安全检查)。
2. 数组的操作
🔹 遍历数组
pub fn main() void {
const arr = [_]i32{5, 10, 15, 20};
for (arr) |value| {
std.debug.print("{}\n", .{value});
}
}
_
让 Zig 自动推断数组长度。for (arr) |value| {}
遍历数组。
🔹 获取数组长度
const arr = [_]i32{10, 20, 30};
const length = arr.len; // 3
3. 多维数组
Zig 支持 多维数组,但维度必须在编译时确定。
🔹 2D 数组示例
const matrix: [2][3]i32 = [2][3]i32{
[3]i32{1, 2, 3},
[3]i32{4, 5, 6},
};
pub fn main() void {
std.debug.print("matrix[1][2]: {}\n", .{matrix[1][2]}); // 输出: 6
}
[2][3]i32
:2 行 3 列的整数矩阵。matrix[1][2]
访问 第 2 行第 3 列的值(6)。
4. 切片基础
切片(Slice) 是数组的引用,大小可以动态变化,但 本质上仍然是指针,没有独立的存储空间。
🔹 定义切片
const arr = [_]i32{10, 20, 30, 40, 50};
const slice: []const i32 = arr[1..4]; // 取索引 1 到 3 的元素
arr[1..4]
:从索引1
到4
(不包含4
)。slice
指向[20, 30, 40]
,但不复制数据。
🔹 访问切片元素
const std = @import("std");
pub fn main() void {
const arr = [_]i32{1, 2, 3, 4, 5};
const slice = arr[1..4]; // [2, 3, 4]
for (slice) |value| {
std.debug.print("{}\n", .{value});
}
}
⚠ 切片只是数组的一个视图,不能修改原始数组的大小!
5. 切片操作
🔹 获取切片长度
const slice = arr[1..4];
const length = slice.len; // 3
🔹 通过索引访问切片
const val = slice[0]; // 2
🔹 修改切片(可变切片)
如果切片是可变的(var
定义),可以修改元素:
var arr = [_]i32{1, 2, 3, 4, 5};
var slice = arr[1..4]; // [2, 3, 4]
slice[0] = 100; // 修改 arr[1]
6. 动态分配切片(std.ArrayList)
Zig 的数组大小固定,但可以使用 std.ArrayList
来实现动态数组。
🔹 使用 std.ArrayList
const std = @import("std");
pub fn main() void {
var gpa = std.heap.page_allocator;
var list = std.ArrayList(i32).init(gpa);
list.append(10) catch unreachable;
list.append(20) catch unreachable;
list.append(30) catch unreachable;
std.debug.print("动态数组: {}\n", .{list.items});
list.deinit(); // 释放内存
}
std.ArrayList(i32)
:创建动态数组。append(value)
:追加元素。list.items
:访问存储的切片。deinit()
:释放分配的内存。
7. 数组 vs. 切片
特性 | 数组 | 切片 |
---|---|---|
大小 | 固定 | 动态 |
内存 | 直接存储数据 | 指向数组的一部分 |
可变性 | 不可改变大小 | 可指向不同的数组部分 |
性能 | 更快 | 稍慢(指针访问) |
动态分配 | ❌ | ✅(std.ArrayList ) |
发表回复