An `unsafe` block permits a small set of operations that ordinary Rust code forbids. It does not switch off Rust’s safety rules: the programmer must uphold rules the compiler cannot check. This matters when Rust works with memory supplied by C, whose validity the Rust compiler cannot establish. section 3.1 section 3.0
Operations that require an unsafe context include:
- Dereferencing a raw pointer or calling a function marked `unsafe`. section 3.1
- Implementing an unsafe trait, mutating a static value, or accessing a union field. section 3.1
Raw pointers are a common reason to use a block. Getting a pointer with `Vec::as_ptr()` is safe; dereferencing it requires `unsafe`. Unlike a Rust reference, a raw pointer carries no lifetime or ownership information the compiler can use to verify that its address is valid. section 3.1.1
Listing 3.1 Reading the elements of a vector using pointer arithmetic
fn main() {
let data: Vec<u8> = vec![5, 10, 15, 20]; #1
read_u8_slice(data.as_ptr(), data.len()); #2
}
fn read_u8_slice(slice_p: *const u8, length: usize) { #3
for index in 0..length {
unsafe { #4
println!("slice[{}] = {}", index,
*slice_p.offset(index as isize)); #5
}
}
}
The vector example keeps pointer creation outside `unsafe` and places the pointer-arithmetic dereference inside it. section 3.1.1
Writing through a C output pointer
A Rust function called from C receives `solution: *mut c_int`. It first checks `solution.is_null()` and returns an error if it is null. The assignment `*solution = 1024` then goes inside `unsafe { ... }`, because it dereferences the pointer. The null check addresses one danger; it does not make every possible pointer valid. section 3.2.2
The same boundary arises when reading a C string: after checking the pointer for null, `CStr::from_ptr(line)` is called inside an `unsafe` block. The resulting C string can then be converted to a Rust string slice without copying the underlying string. section 3.2.2


