In this lesson, you will learn how to bypass Rust's strict safety checks by using raw pointers to interact directly with memory addresses.
What are Raw Pointers?
In safe Rust, the compiler guarantees that references like &T or &mut T are always valid, non-null, and follow strict ownership rules. Sometimes, however, you need to perform low-level tasks—like interacting with hardware or implementing a custom data structure—where you need more control.
Raw pointers, denoted as *const T (immutable) and *mut T (mutable), allow you to ignore these rules. They are "raw" because the compiler stops tracking their validity, meaning they can be null, point to invalid memory, or be aliased in ways that break Rust's memory model.
Working with Raw Memory
Because raw pointers can easily cause crashes or undefined behavior, you must wrap any operation involving them in an unsafe block.
fn main() {
let mut value = 10;
// Create raw pointers from references
let ptr = &value as *const i32;
let mut_ptr = &mut value as *mut i32;
unsafe {
// Dereference the pointer to read or change the value
println!("Value at memory address: {}", *ptr);
// Write a new value through the mutable raw pointer
*mut_ptr = 20;
}
println!("New value: {}", value);
}
In this example, we manually grab the memory address of value and turn it into a pointer. Inside the unsafe block, we dereference it using the * operator. Note that unsafe is not a "magic pass"—it is a contract between you and the compiler where you promise that the memory address you are accessing is currently valid and correctly aligned.
Why use them?
While you should almost always prefer safe references, raw pointers are essential for performance-intensive tasks or when building abstractions that rely on specific memory layouts (like a linked list) that the borrow checker might otherwise reject. By moving into the unsafe zone, you assume full responsibility for preventing memory corruption.
Key Takeaway: Raw pointers provide raw access to memory addresses without the compiler's safety nets, requiring you to manually ensure memory validity within unsafe blocks.