Zig Arrays and Slices
In the Zig programming language, arrays and slices are fundamental structures for storing and manipulating a set of data of the same type.
- Array: Used to store a fixed-size set of data of the same type, with the size specified at definition time and stored on the stack.
- Slice: Used to reference a portion of an array or other contiguous memory region. Its size can be dynamically adjusted, making it more flexible, and it usually references heap memory.
Array:
- An array is a fixed-length sequence whose size is determined at compile time.
- The type of an array is
[T], whereTis the type of the elements in the array. - Array memory is contiguous, which gives them a performance advantage, especially when processing large amounts of data.
Slice:
- A slice is a dynamically sized sequence that allows its size to be changed at runtime.
- The type of a slice is
[]T, whereTis the type of the elements in the slice. - A slice is actually a reference to an array; it contains a pointer to the array and the length of the slice.
- Slices can handle data more flexibly because they can be easily shared and passed between different arrays.
Array
Arrays are fixed-size, stored on the stack, and the element types must be the same.
You can use the[]syntax to define an array and specify its size.
The type of an array is defined as[T; N], where T is the type of the array elements and N is the length of the array.
Array elements can be accessed by index, with indexing starting from00.
Syntax
const arrayName: [size]ElementType = [size]ElementType{element1, element2, ...};
Parameter description:
arrayName: The name of the array.size: The size of the array (number of elements), which is a compile-time constant.ElementType: The type of the elements in the array.element1, element2, ...: The elements in the array.
An array is a fixed-size contiguous memory block whose size is determined at compile time:
var myArray: [10]u8 = [10]u8{0} ** 10; // 定义并初始化一个大小为 10 的 u8 类型数组
Example
pub fn main() void {
// Define an array containing 5 elements of type i32
const arr: [5]i32 = [5]i32{1, 2, 3, 4, 5};
// Access array elements by index
std.debug.print("First element: {}\n", .{arr[0]});
std.debug.print("Third element: {}\n", .{arr[2]});
// The size of the array is fixed
const size: usize = arr.len;
std.debug.print("Array size: {}\n", .{size});
}
The compilation output is:
First element: 1 Third element: 3 Array size: 5
Iterating Over an Array
You can use aforloop to iterate over the elements of an array.
Example
pub fn main() void {
const arr: [5]i32 = [5]i32{ 1, 2, 3, 4, 5 };
var index: usize = 0;
// Iterate over the array
for (arr) |item| {
std.debug.print("Index: {}, Item: {}\n", .{ index, item });
index += 1;
}
}
The compilation output is:
Index: 0, Item: 1 Index: 1, Item: 2 Index: 2, Item: 3 Index: 3, Item: 4 Index: 4, Item: 5
Slice
A slice is a reference to a portion of an array or other contiguous memory region.
A slice can dynamically adjust its size and is more flexible than an array, but its elements are stored on the heap.
Definition and Initialization
A slice is a reference to a portion of an array or other contiguous memory region.
A slice is dynamic and can change its size; it is often used to represent a portion of an array or a dynamically allocated memory block.
Syntax
const sliceName: []ElementType = array[start..end];
Parameter description:
sliceName: The name of the slice.ElementType: The type of the elements in the slice.array[start..end]: Fromarrayextract a sub-slice,startandendis the index.
A slice can be created from a subset of an array, or it can be created from a pointer and a length:
var myArray: [10]u8 = ...; // 假设已经初始化 var mySlice = myArray[2..7]; // 创建一个切片,包含索引2到6的元素 // 或者使用指针和长度 var mySlicePtr = myArray[2..]; // 创建一个切片,从索引2开始到数组末尾
Slices provide some built-in methods for manipulating slices, for example:
len: Gets the length of the slice.ptr: Gets the pointer of the slice.capacity: Gets the capacity of the slice, i.e., the maximum length of the array portion it can reference.
Example
pub fn main() void {
var arr: [5]i32 = [5]i32{ 1, 2, 3, 4, 5 };
// Create a slice from an array
const slice: []i32 = arr[1..4];
// Access slice elements by index
std.debug.print("First element of slice: {}\n", .{slice[0]});
std.debug.print("Second element of slice: {}\n", .{slice[1]});
// The length of the slice
const length: usize = slice.len;
std.debug.print("Slice length: {}\n", .{length});
}
The compilation output is:
First element of slice: 2 Second element of slice: 3 Slice length: 3
Iterating Over a Slice
Similar to arrays, you can use aforloop to iterate over the slice.
Example
pub fn main() void {
var arr: [5]i32 = [5]i32{ 1, 2, 3, 4, 5 };
const slice: []i32 = arr[1..4];
var index: usize = 1;
// Iterate over the slice
for (slice) |item| {
std.debug.print("Index: {}, Item: {}\n", .{ index, item });
index += 1;
}
}
The compilation output is:
Index: 1, Item: 2 Index: 2, Item: 3 Index: 3, Item: 4
Differences Between Arrays and Slices
- Size: The size of an array is fixed and determined when defined; the size of a slice can be dynamically adjusted.
- Storage location: Arrays are usually stored on the stack, while the memory referenced by a slice can be on the heap.
- Flexibility: Slices are more flexible and can reference a portion of an array or dynamically allocated memory.
| Feature | Array | Slice |
|---|---|---|
| Size | Fixed, determined at compile time | Dynamic, size can be changed |
| Element type | Same | Same |
| Memory location | Usually on the stack (local variables) | Referenced memory may be on the heap or the stack |
| Access | By index | By the start and end indices of the slice |
| Creation | Direct definition | Created from an array or another slice |
In the following example, the printArray function takes a fixed-size array as a parameter, while the printSlice function takes a slice as a parameter. Through these functions, you can see the differences between arrays and slices in passing and usage.
Example
fn printArray(arr: [5]i32) void {
for (arr) |item| {
std.debug.print("Array item: {}\n", .{item});
}
}
fn printSlice(slice: []const i32) void {
for (slice) |item| {
std.debug.print("Slice item: {}\n", .{item});
}
}
pub fn main() void {
const arr: [5]i32 = [5]i32{ 1, 2, 3, 4, 5 };
const slice: []const i32 = arr[1..4];
printArray(arr);
printSlice(slice);
}
The compilation output is:
Array item: 1 Array item: 2 Array item: 3 Array item: 4 Array item: 5 Slice item: 2 Slice item: 3 Slice item: 4Other Extensions