Arreglos y slices de Zig
En el lenguaje de programación Zig, los arreglos y los slices son estructuras básicas utilizadas para almacenar y manipular un conjunto de datos del mismo tipo.
- Arreglo: se utilizan para almacenar un conjunto de datos del mismo tipo de tamaño fijo. El tamaño se especifica al definirlo y se almacenan en la pila.
- Slice: se utilizan para referenciar una parte de un arreglo u otra región de memoria contigua. Su tamaño se puede ajustar dinámicamente, son más flexibles y normalmente hacen referencia a memoria del montón.
Arreglo (Array):
- Un arreglo es una secuencia de longitud fija cuyo tamaño ya se determina en tiempo de compilación.
- El tipo de un arreglo es
[T], dondeTes el tipo de los elementos del arreglo. - La memoria de los arreglos es contigua, lo que les brinda una gran ventaja en rendimiento, especialmente al manejar grandes cantidades de datos.
Slice:
- Un slice es una secuencia de longitud dinámica que permite cambiar su tamaño en tiempo de ejecución.
- El tipo de un slice es
[]T, dondeTes el tipo de los elementos del slice. - Un slice es en realidad una referencia a un arreglo; contiene un puntero al arreglo y la longitud del slice.
- Los slices pueden manejar datos de manera más flexible porque pueden compartirse y transferirse fácilmente entre diferentes arreglos.
Arreglos
Los arreglos son de tamaño fijo, se almacenan en la pila y los tipos de sus elementos deben ser iguales.
Se puede usar[]sintaxis para definir un arreglo y especificar su tamaño.
El tipo de un arreglo se define como[T; N], donde T es el tipo de los elementos del arreglo y N es la longitud del arreglo.
Los elementos de un arreglo se acceden mediante un índice; el índice comienza en0.
Formato de sintaxis
const arrayName: [size]ElementType = [size]ElementType{element1, element2, ...};
Descripción de parámetros:
arrayName: el nombre del arreglo.size: el tamaño del arreglo (número de elementos), que es una constante en tiempo de compilación.ElementType: el tipo de los elementos del arreglo.element1, element2, ...: los elementos del arreglo.
Un arreglo es un bloque de memoria contiguo de tamaño fijo, cuyo tamaño ya se determina en tiempo de compilación:
var myArray: [10]u8 = [10]u8{0} ** 10; // 定义并初始化一个大小为 10 的 u8 类型数组
Ejemplo
pub fn main() void {
// Define un arreglo que contiene 5 elementos de tipo i32
const arr: [5]i32 = [5]i32{1, 2, 3, 4, 5};
// Accede a los elementos del arreglo mediante un índice
std.debug.print("First element: {}\n", .{arr[0]});
std.debug.print("Third element: {}\n", .{arr[2]});
// El tamaño del arreglo es fijo
const size: usize = arr.len;
std.debug.print("Array size: {}\n", .{size});
}
El resultado de la compilación es:
First element: 1 Third element: 3 Array size: 5
Recorrer arreglos
Se puede usarforun bucle para recorrer los elementos de un arreglo.
Ejemplo
pub fn main() void {
const arr: [5]i32 = [5]i32{ 1, 2, 3, 4, 5 };
var index: usize = 0;
// Recorrer el arreglo
for (arr) |item| {
std.debug.print("Index: {}, Item: {}\n", .{ index, item });
index += 1;
}
}
El resultado de la compilación es:
Index: 0, Item: 1 Index: 1, Item: 2 Index: 2, Item: 3 Index: 3, Item: 4 Index: 4, Item: 5
Slice (segmento)
Un slice es una referencia a una parte de un arreglo u otra región de memoria contigua.
Un slice puede ajustar su tamaño dinámicamente y es más flexible que un arreglo, pero sus elementos se almacenan en el montón.
Definición e inicialización
Un slice es una referencia a una parte de un arreglo u otra región de memoria contigua.
Los slices son dinámicos, pueden cambiar su tamaño y generalmente se usan para representar una parte de un arreglo o un bloque de memoria asignado dinámicamente.
Formato de sintaxis
const sliceName: []ElementType = array[start..end];
Descripción de parámetros:
sliceName: el nombre del slice.ElementType: el tipo de los elementos del slice.array[start..end]: a partir dearrayse extrae un subslice,startyendes el índice.
Un slice se puede crear a partir de un subconjunto de un arreglo, o también mediante un puntero y una longitud:
var myArray: [10]u8 = ...; // 假设已经初始化 var mySlice = myArray[2..7]; // 创建一个切片,包含索引2到6的元素 // 或者使用指针和长度 var mySlicePtr = myArray[2..]; // 创建一个切片,从索引2开始到数组末尾
Los slices proporcionan algunos métodos integrados para manipularlos, por ejemplo:
len: obtiene la longitud del slice.ptr: obtiene el puntero del slice.capacity: obtiene la capacidad del slice, es decir, la longitud máxima de la parte del arreglo que puede referenciar.
Ejemplo
pub fn main() void {
var arr: [5]i32 = [5]i32{ 1, 2, 3, 4, 5 };
// Crear un slice a partir de un arreglo
const slice: []i32 = arr[1..4];
// Acceder a los elementos del slice mediante un índice
std.debug.print("First element of slice: {}\n", .{slice[0]});
std.debug.print("Second element of slice: {}\n", .{slice[1]});
// La longitud del slice
const length: usize = slice.len;
std.debug.print("Slice length: {}\n", .{length});
}
El resultado de la compilación es:
First element of slice: 2 Second element of slice: 3 Slice length: 3
Recorrer slices
Similar a los arreglos, se puede usarforun bucle para recorrer slices.
Ejemplo
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;
// Recorrer el slice
for (slice) |item| {
std.debug.print("Index: {}, Item: {}\n", .{ index, item });
index += 1;
}
}
El resultado de la compilación es:
Index: 1, Item: 2 Index: 2, Item: 3 Index: 3, Item: 4
Diferencias entre arreglos y slices
- Tamaño: el tamaño de un arreglo es fijo y se determina al definirlo; el tamaño de un slice se puede ajustar dinámicamente.
- Ubicación de almacenamiento: los arreglos normalmente se almacenan en la pila, mientras que la memoria referenciada por un slice puede estar en el montón.
- Flexibilidad: los slices son más flexibles y pueden referenciar una parte de un arreglo o memoria asignada dinámicamente.
| Característica | Arreglo | Slice |
|---|---|---|
| Tamaño | Fijo, determinado en tiempo de compilación | Dinámico, puede cambiar de tamaño |
| Tipo de elementos | Igual | Igual |
| Ubicación en memoria | Generalmente en la pila (variables locales) | La memoria referenciada puede estar en el montón o en la pila |
| Acceso | Mediante un índice | Mediante los índices de inicio y fin del slice |
| Creación | Definición directa | Se crea a partir de un arreglo u otro slice |
En el siguiente ejemplo, la función printArray acepta un arreglo de tamaño fijo como parámetro, mientras que la función printSlice acepta un slice como parámetro. A través de estas funciones, se pueden ver las diferencias entre arreglos y slices en cuanto a su paso y uso.
Ejemplo
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);
}
El resultado de la compilación es:
Array item: 1 Array item: 2 Array item: 3 Array item: 4 Array item: 5 Slice item: 2 Slice item: 3 Slice item: 4Otras extensiones