There are five things you can do in unsafe Rust but not in safe Rust:
union
sIt’s important to understand that unsafe
doesn’t turn off the borrow checker or disable any other of Rust’s safety checks: if you use a reference in unsafe code, it will still be checked. The unsafe
keyword only gives you access to these five features that are then not checked by the compiler for memory safety. You’ll still get some degree of safety inside of an unsafe block.
Unsafe Rust has two new types called raw pointers that are similar to references. As with references, raw pointers can be immutable or mutable and are written as *const T
and *mut T
, respectively. The asterisk isn’t the dereference operator; it’s part of the type name.
Different from references and smart pointers, raw pointers:
fn main() {
let mut num = 5;
let r1 = &num as *const i32; // we can create raw pointer outside unsafe block
let r2 = &mut num as *mut i32;
let a = *r1; // not ok, we can't dereference it outside unsafe block
unsafe {
let b = *r2; // ok
}
}
We can make a pointer from potentially undefined memory location:
fn main() {
let address = 0x012345usize;
let r = address as *const i32;
}
Why would you ever use raw pointers? One major use case is when interfacing with C code. Another case is when building up safe abstractions that the borrow checker doesn’t understand.