Массивы и срезы Zig
В языке программирования Zig массивы и срезы — это фундаментальные структуры для хранения и обработки набора данных одного типа.
- Массив: Используется для хранения набора данных одного типа фиксированного размера, при этом размер задаётся при определении, а массив хранится в стеке.
- Срез: Используется для ссылки на часть массива или другой непрерывной области памяти. Его размер может динамически изменяться, что делает его более гибким, и обычно он ссылается на память в куче.
Массив:
- Массив — это последовательность фиксированной длины, размер которой определяется во время компиляции.
- Тип массива —
[T], гдеT— это тип элементов в массиве. - Память массивов непрерывна, что даёт им преимущество в производительности, особенно при обработке больших объёмов данных.
Срез:
- Срез — это последовательность динамического размера, размер которой можно изменять во время выполнения.
- Тип среза —
[]T, гдеT— это тип элементов в срезе. - Срез на самом деле является ссылкой на массив; он содержит указатель на массив и длину среза.
- Срезы позволяют более гибко работать с данными, поскольку их можно легко совместно использовать и передавать между разными массивами.
Массив
Массивы имеют фиксированный размер, хранятся в стеке, и типы элементов должны быть одинаковыми.
Вы можете использовать синтаксис[], чтобы определить массив и указать его размер.
Тип массива определяется как[T; N], где T — тип элементов массива, а N — длина массива.
Доступ к элементам массива осуществляется по индексу, индексация начинается с00.
Синтаксис
const arrayName: [size]ElementType = [size]ElementType{element1, element2, ...};
Описание параметра:
arrayName: Имя массива.size: Размер массива (количество элементов), который является константой времени компиляции.ElementType: Тип элементов в массиве.element1, element2, ...: Элементы в массиве.
Массив — это непрерывный блок памяти фиксированного размера, размер которого определяется во время компиляции:
var myArray: [10]u8 = [10]u8{0} ** 10; // 定义并初始化一个大小为 10 的 u8 类型数组
Пример
pub fn main() void {
// Определить массив, содержащий 5 элементов типа i32
const arr: [5]i32 = [5]i32{1, 2, 3, 4, 5};
// Доступ к элементам массива по индексу
std.debug.print("Первый элемент: {}\n", .{arr[0]});
std.debug.print("Третий элемент: {}\n", .{arr[2]});
// Размер массива фиксирован
const size: usize = arr.len;
std.debug.print("Размер массива: {}\n", .{size});
}
Вывод компиляции:
First element: 1 Third element: 3 Array size: 5
Итерация по массиву
Вы можете использовать циклforдля перебора элементов массива.
Пример
pub fn main() void {
const arr: [5]i32 = [5]i32{ 1, 2, 3, 4, 5 };
var index: usize = 0;
// Перебрать массив
for (arr) |item| {
std.debug.print("Индекс: {}, Элемент: {}\n", .{ index, item });
index += 1;
}
}
Вывод компиляции:
Index: 0, Item: 1 Index: 1, Item: 2 Index: 2, Item: 3 Index: 3, Item: 4 Index: 4, Item: 5
Срез
Срез — это ссылка на часть массива или другой области непрерывной памяти.
Срез может динамически изменять свой размер и более гибок, чем массив, но его элементы хранятся в куче.
Определение и инициализация
Срез — это ссылка на часть массива или другой области непрерывной памяти.
Срез динамичен и может изменять свой размер; он часто используется для представления части массива или динамически выделенного блока памяти.
Синтаксис
const sliceName: []ElementType = array[start..end];
Описание параметра:
sliceName: Имя среза.ElementType: Тип элементов в срезе.array[start..end]: Отarrayизвлечь подсрез,startиendэто индекс.
Срез можно создать из подмножества массива или из указателя и длины:
var myArray: [10]u8 = ...; // 假设已经初始化 var mySlice = myArray[2..7]; // 创建一个切片,包含索引2到6的元素 // 或者使用指针和长度 var mySlicePtr = myArray[2..]; // 创建一个切片,从索引2开始到数组末尾
Срезы предоставляют некоторые встроенные методы для управления срезами, например:
len: Возвращает длину среза.ptr: Возвращает указатель на срез.capacity: Возвращает ёмкость среза, то есть максимальную длину части массива, на которую он может ссылаться.
Пример
pub fn main() void {
var arr: [5]i32 = [5]i32{ 1, 2, 3, 4, 5 };
// Создать срез из массива
const slice: []i32 = arr[1..4];
// Доступ к элементам среза по индексу
std.debug.print("Первый элемент среза: {}\n", .{slice[0]});
std.debug.print("Второй элемент среза: {}\n", .{slice[1]});
// Длина среза
const length: usize = slice.len;
std.debug.print("Длина среза: {}\n", .{length});
}
Вывод компиляции:
First element of slice: 2 Second element of slice: 3 Slice length: 3
Итерация по срезу
Как и в случае с массивами, можно использовать циклforдля перебора среза.
Пример
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;
// Перебор среза
for (slice) |item| {
std.debug.print("Индекс: {}, Элемент: {}\n", .{ index, item });
index += 1;
}
}
Вывод компиляции:
Index: 1, Item: 2 Index: 2, Item: 3 Index: 3, Item: 4
Различия между массивами и срезами
- Размер: Размер массива фиксирован и определяется при объявлении; размер среза может динамически изменяться.
- Место хранения: Массивы обычно хранятся в стеке, тогда как память, на которую ссылается срез, может находиться в куче.
- Гибкость: Срезы более гибкие и могут ссылаться на часть массива или динамически выделенную память.
| Характеристика | Массив | Срез |
|---|---|---|
| Size | Фиксированный, определяется во время компиляции | Динамический, размер можно изменять |
| Тип элемента | То же самое | То же самое |
| Расположение в памяти | Обычно в стеке (локальные переменные) | Память, на которую ссылаются, может находиться в куче или стеке |
| Access | По индексу | По начальному и конечному индексам среза |
| Создание | Прямое определение | Создаётся из массива или другого среза |
В следующем примере функция printArray принимает в качестве параметра массив фиксированного размера, а функция printSlice принимает в качестве параметра срез. На этих функциях можно увидеть различия между массивами и срезами при передаче и использовании.
Пример
fn printArray(arr: [5]i32) void {
for (arr) |item| {
std.debug.print("Элемент массива: {}\n", .{item});
}
}
fn printSlice(slice: []const i32) void {
for (slice) |item| {
std.debug.print("Элемент среза: {}\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);
}
Вывод компиляции:
Array item: 1 Array item: 2 Array item: 3 Array item: 4 Array item: 5 Slice item: 2 Slice item: 3 Slice item: 4Другие расширения