Uses of & and * in Rust: Understanding References and Dereferencing in Read/Write Operations

Henry Tirla
3 min readAug 27, 2024

In Rust, the symbols & and * play crucial roles in managing references and dereferencing, particularly in the context of variable read and write operations. Understanding how these operators work is essential for effectively using Rust's ownership and borrowing rules.

1. `&` Operator: Creating References

The & operator is used to create a reference to a value. References allow you to access a value without taking ownership, enabling you to read or (if mutable) modify the value without moving it.

Immutable Reference (&T)

  • Read Access: When you create an immutable reference to a variable using &, you can read the value, but you cannot modify it.
fn main() {
let x = 10;
let y = &x; // `y` is an immutable reference to `x`

println!("Value of x: {}", *y);
// Dereferencing `y` to access the value of `x`
// *y += 1; // Error: cannot modify an immutable reference
}
  • Example: In the above code, y is an immutable reference to x. You can use y to read the value of x by dereferencing it with *y.

Mutable Reference (&mut T)

  • Write Access: When you create a mutable reference using &mut, you can both read and modify the value.
fn main() {
let mut x = 10;
let y = &mut x; // `y` is a mutable reference to `x`

*y += 5; // Modifying the value of `x` through `y`
println!("Value of x: {}", x); // x is now 15
}

Example: In this example, y is a mutable reference to x. You can modify the value of x through y using dereferencing with *y.

2. `*` Operator: Dereferencing

The * operator is used to dereference a reference, which means accessing the value that the reference points to.

Dereferencing Immutable References

  • Read Operations: With an immutable reference, you use the * operator to access the value without modifying it.
fn main() {
let x = 20;
let y = &x;

println!("Dereferenced value: {}", *y);
// Accessing the value of `x` through `y`
}
  • Example: *y accesses the value of x through the reference y.

Dereferencing Mutable References

  • Write Operations: With a mutable reference, dereferencing allows you to both read and modify the value.
fn main() {
let mut x = 30;
let y = &mut x;

*y += 10; // Modifying the value of `x` through the mutable reference `y`
println!("New value of x: {}", x); // x is now 40
}
  • Example: Here, *y allows you to modify the value of x via the mutable reference y.

3. Practical Considerations in Read/Write Operations

Multiple Immutable References

  • Safe Read Access: You can have multiple immutable references to a variable simultaneously. This allows safe concurrent read access without any risk of data races.
fn main() {
let x = 50;
let y1 = &x;
let y2 = &x;

println!("y1: {}, y2: {}", *y1, *y2);
// Both y1 and y2 can read x simultaneously
}

Single Mutable Reference

  • Exclusive Write Access: You can only have one mutable reference to a variable at a time. This exclusive access ensures that no other references can interfere, preventing data races during modification.
fn main() {
let mut x = 60;
let y = &mut x; // Only one mutable reference is allowed

*y += 20;
println!("Value of x after modification: {}", x);
// No other reference can access x while y is active
}

Mixing Immutable and Mutable References

  • Mutual Exclusion: You cannot have a mutable reference while immutable references exist. This rule ensures that no data inconsistencies occur during simultaneous read and write operations.
fn main() {
let mut x = 70;
let y1 = &x; // Immutable reference
let y2 = &x; // Another immutable reference

// let y3 = &mut x; // Error: cannot borrow `x` as mutable because it is already borrowed as immutable

println!("y1: {}, y2: {}", *y1, *y2);
}

Invalid Scenario: The code would fail to compile if you tried to create y3 as a mutable reference while y1 and y2 are still in scope.

Summary

  • & (Reference Creation):
  • &x creates an immutable reference to x, allowing read-only access.
  • &mut x creates a mutable reference to x, allowing both read and write access.
  • * (Dereferencing):
  • *y dereferences the reference y, giving you access to the value it points to.
  • With immutable references (&T), dereferencing is for reading.
  • With mutable references (&mut T), dereferencing allows both reading and writing.

These concepts ensure Rust’s memory safety and concurrency guarantees, enabling fine-grained control over how data is accessed and modified.

Sign up to discover human stories that deepen your understanding of the world.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Responses (1)

Write a response