4/5
## Rust Arrays vs. Slices: The Core Distinction In Rust, both arrays and slices are used to handle collections of elements of the same type. However, they differ fundamentally in how their length is managed, which has significant implications for their usage. * **Arrays:** An array is a collection of elements where its **length is known at compile time**. This means the size of the array must be a constant value, determined when your Rust program is compiled. This fixed-size nature allows for stack allocation and efficient access. * **Slices:** A slice, on the other hand, is a collection of elements where its **length is not necessarily known at compile time**. The length of a slice can be determined at runtime. Slices are typically views or "slices" into a part of an array or another collection type like a Vector. This dynamic sizing provides flexibility. Understanding this core difference is crucial for effectively using these data structures in Rust. ## Working with Arrays in Rust Arrays in Rust are a fundamental way to store a fixed number of elements of the same type contiguously in memory. **Declaration and Initialization** An array's type signature includes both the type of its elements and its fixed length. This is specified as `[T; N]`, where `T` is the element type and `N` is the compile-time constant length. Consider the following example: ```rust // Array let arr: [u32; 3] = [1, 2, 3]; ``` * `let arr`: Declares an immutable variable named `arr`. * `[u32; 3]`: This is the type annotation. It signifies an array (`[]`) containing elements of type `u32` (unsigned 32-bit integers) with a fixed length of `3`. * `= [1, 2, 3];`: Initializes the array with the values 1, 2, and 3. **Accessing Array Elements** Elements within an array are accessed using 0-based indexing, meaning the first element is at index 0, the second at index 1, and so on. ```rust // Accessing an element from the 'arr' defined above println!("arr[0]: {}", arr[0]); ``` This code snippet accesses the first element (at index 0) of the `arr`. When executed, the output would be: ``` arr[0]: 1 ``` **Mutability and Writing to Arrays** By default, variables in Rust, including arrays, are immutable. To modify an array's contents after its initial declaration, you must declare it as mutable using the `mut` keyword. ```rust // Write let mut arr: [u32; 3] = [1, 2, 3]; arr[1] = 99; // To observe the change, you can print the array: // println!("{:?}", arr); // This would output: [1, 99, 3] ``` * `let mut arr`: Declares a *mutable* array named `arr`. * `arr[1] = 99;`: Modifies the element at index 1 (the second element) to the value `99`. **Initializing Arrays with a Default Value** Rust provides a convenient shorthand syntax to initialize all elements of an array to the same default value. ```rust let arr: [u32; 10] = [0; 10]; println!("arr: {:?}", arr); ``` * `[0; 10]`: This syntax creates an array of `u32` elements with a length of 10. Every element in this array is initialized to `0`. * `println!("arr: {:?}", arr);`: Uses debug formatting (`{:?}`) to print the entire array. The output for this code will be: ``` arr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ``` ## Understanding Slices in Rust Slices in Rust provide a powerful and flexible way to reference a contiguous sequence of elements within another collection, such as an array or a Vector. Unlike arrays, slices do not own the data they point to; they are "views" or "references." To illustrate slicing, let's first define a base array: ```rust // Slice let nums: [i32; 10] = [-1, 1, -2, 2, -3, 3, -4, 4, -5, 5]; // Corresponding indices: 0 1 2 3 4 5 6 7 8 9 ``` This array, `nums`, contains ten signed 32-bit integers (`i32`). **Creating Slices** Slices are, by their nature, references. Therefore, they are prefixed with an ampersand (`&`). The type of an immutable slice is `&[T]`, where `T` is the type of the elements it references. The syntax for creating a slice from an array `arr_name` is `&arr_name[start_index..end_index]`. It's important to note that `start_index` is inclusive, while `end_index` is exclusive. **Example: Slicing the first 3 elements** To get a slice containing the first three elements of our `nums` array (elements at indices 0, 1, and 2): ```rust let s: &[i32] = &nums[0..3]; // References elements -1, 1, -2 ``` This creates a slice `s` of type `&[i32]` that references the sub-sequence `[-1, 1, -2]` from the `nums` array. **Example: Slicing the last 3 elements** To get a slice of the last three elements (indices 7, 8, and 9): ```rust let s: &[i32] = &nums[7..10]; // References elements 4, -5, 5 ``` This slice `s` will reference the sub-sequence `[4, -5, 5]`. **Example: Slicing the middle 4 elements** To obtain a slice of four elements from the middle of the array (e.g., indices 3, 4, 5, and 6): ```rust let s: &[i32] = &nums[3..7]; // References elements 2, -3, 3, -4 println!("mid 4: {:?}", s); ``` The `println!` statement will output: ``` mid 4: [2, -3, 3, -4] ``` **Slice Syntax Shorthands** Rust offers convenient shorthands for common slicing operations: * **Slicing from the beginning:** If you want to slice from the start of the array (index 0) up to a certain `end_index` (exclusive), you can omit the `0`. `&array[..end_index]` is equivalent to `&array[0..end_index]`. For instance, `&nums[..3]` is the same as `&nums[0..3]`. * **Slicing to the end:** If you want to slice from a `start_index` (inclusive) to the very end of the array, you can omit the `end_index`. Rust will infer it as the length of the array. `&array[start_index..]` is equivalent to `&array[start_index..array.len()]`. For example, `&nums[7..]` is the same as `&nums[7..10]` for our `nums` array of length 10. * **Slicing the entire array:** To create a slice that references the entire array, you can use: `&array[..]` **The Nature of Slices: They are References** A crucial point to remember is that slices *borrow* data from their source (e.g., an array or Vector). They do not own the data themselves. This is a core concept in Rust's ownership and borrowing system, ensuring memory safety. The lifetime of a slice cannot outlive the lifetime of the data it references. While not explicitly detailed in these examples, you can also have mutable slices (`&mut [T]`) if the underlying data source is mutable, allowing for modification of the borrowed data.
In Rust, both arrays and slices are used to handle collections of elements of the same type. However, they differ fundamentally in how their length is managed, which has significant implications for their usage.
Arrays: An array is a collection of elements where its length is known at compile time. This means the size of the array must be a constant value, determined when your Rust program is compiled. This fixed-size nature allows for stack allocation and efficient access.
Slices: A slice, on the other hand, is a collection of elements where its length is not necessarily known at compile time. The length of a slice can be determined at runtime. Slices are typically views or "slices" into a part of an array or another collection type like a Vector. This dynamic sizing provides flexibility.
Understanding this core difference is crucial for effectively using these data structures in Rust.
Arrays in Rust are a fundamental way to store a fixed number of elements of the same type contiguously in memory.
Declaration and Initialization
An array's type signature includes both the type of its elements and its fixed length. This is specified as [T; N]
, where T
is the element type and N
is the compile-time constant length.
Consider the following example:
let arr
: Declares an immutable variable named arr
.
[u32; 3]
: This is the type annotation. It signifies an array ([]
) containing elements of type u32
(unsigned 32-bit integers) with a fixed length of 3
.
= [1, 2, 3];
: Initializes the array with the values 1, 2, and 3.
Accessing Array Elements
Elements within an array are accessed using 0-based indexing, meaning the first element is at index 0, the second at index 1, and so on.
This code snippet accesses the first element (at index 0) of the arr
. When executed, the output would be:
Mutability and Writing to Arrays
By default, variables in Rust, including arrays, are immutable. To modify an array's contents after its initial declaration, you must declare it as mutable using the mut
keyword.
let mut arr
: Declares a mutable array named arr
.
arr[1] = 99;
: Modifies the element at index 1 (the second element) to the value 99
.
Initializing Arrays with a Default Value
Rust provides a convenient shorthand syntax to initialize all elements of an array to the same default value.
[0; 10]
: This syntax creates an array of u32
elements with a length of 10. Every element in this array is initialized to 0
.
println!("arr: {:?}", arr);
: Uses debug formatting ({:?}
) to print the entire array.
The output for this code will be:
Slices in Rust provide a powerful and flexible way to reference a contiguous sequence of elements within another collection, such as an array or a Vector. Unlike arrays, slices do not own the data they point to; they are "views" or "references."
To illustrate slicing, let's first define a base array:
This array, nums
, contains ten signed 32-bit integers (i32
).
Creating Slices
Slices are, by their nature, references. Therefore, they are prefixed with an ampersand (&
). The type of an immutable slice is &[T]
, where T
is the type of the elements it references.
The syntax for creating a slice from an array arr_name
is &arr_name[start_index..end_index]
. It's important to note that start_index
is inclusive, while end_index
is exclusive.
Example: Slicing the first 3 elements
To get a slice containing the first three elements of our nums
array (elements at indices 0, 1, and 2):
This creates a slice s
of type &[i32]
that references the sub-sequence [-1, 1, -2]
from the nums
array.
Example: Slicing the last 3 elements
To get a slice of the last three elements (indices 7, 8, and 9):
This slice s
will reference the sub-sequence [4, -5, 5]
.
Example: Slicing the middle 4 elements
To obtain a slice of four elements from the middle of the array (e.g., indices 3, 4, 5, and 6):
The println!
statement will output:
Slice Syntax Shorthands
Rust offers convenient shorthands for common slicing operations:
Slicing from the beginning: If you want to slice from the start of the array (index 0) up to a certain end_index
(exclusive), you can omit the 0
.
&array[..end_index]
is equivalent to &array[0..end_index]
.
For instance, &nums[..3]
is the same as &nums[0..3]
.
Slicing to the end: If you want to slice from a start_index
(inclusive) to the very end of the array, you can omit the end_index
. Rust will infer it as the length of the array.
&array[start_index..]
is equivalent to &array[start_index..array.len()]
.
For example, &nums[7..]
is the same as &nums[7..10]
for our nums
array of length 10.
Slicing the entire array: To create a slice that references the entire array, you can use:
&array[..]
The Nature of Slices: They are References
A crucial point to remember is that slices borrow data from their source (e.g., an array or Vector). They do not own the data themselves. This is a core concept in Rust's ownership and borrowing system, ensuring memory safety. The lifetime of a slice cannot outlive the lifetime of the data it references. While not explicitly detailed in these examples, you can also have mutable slices (&mut [T]
) if the underlying data source is mutable, allowing for modification of the borrowed data.
An essential comparison of Rust Arrays vs. Slices - Discover why arrays have fixed, compile-time lengths while slices offer flexible, runtime views into data. Explore array definition, initialization, and element manipulation, plus techniques for creating powerful slices.
Previous lesson
Previous
Next lesson
Next
Give us feedback
Course Overview
About the course
Introduction to the Rust programming language
Rust variables and functions
Scalar types, arrays, strings, enum, structs, vectors, and hash maps in Rust
Rust control flows: If / else, if let and let else, loop, match
Rust ownership, including borrow and references
Rust error handling
Rust Modules
Rust Traits
Last updated on July 11, 2025
Rust Developer
Rust Programming BasicsDuration: 6min
Duration: 18min
Duration: 47min
Duration: 15min
Duration: 19min
Duration: 8min
Duration: 12min
Duration: 46min
Duration: 14min
Course Overview
About the course
Introduction to the Rust programming language
Rust variables and functions
Scalar types, arrays, strings, enum, structs, vectors, and hash maps in Rust
Rust control flows: If / else, if let and let else, loop, match
Rust ownership, including borrow and references
Rust error handling
Rust Modules
Rust Traits
Last updated on July 11, 2025