CodeBlanks Logo Icon CodeBlanks

Raw pointers

Use *const T and *mut T raw pointers.

Raw pointers

*const T and *mut T, unlike references: can be null, can point at invalid memory, don't follow borrowing rules and aren't cleaned up automatically. Arithmetic can be done on them:

let v = [10, 20, 30];
let p: *const i32 = v.as_ptr();
unsafe {
    println!("{}", *p.add(1));   // 20
}
println!("{}", p.is_null());     // false
let bos: *const i32 = std::ptr::null();

add(n) advances the pointer by n elements (not bytes). Going outside the array is undefined behaviour.

From references to pointers

Going from a reference to a raw pointer is always safe; the reverse is unsafe because you must guarantee the pointer is valid:

let x = 42;
let p = &x as *const i32;              // safe
let p2 = std::ptr::addr_of!(x);        // the same, without an intermediate reference
let r: &i32 = unsafe { &*p };          // unsafe: p must be valid

Raw pointers are used most in FFI and when writing your own data structures (linked lists, trees).

Practice Pointer arithmetic

Get a pointer with as_ptr() for let v = [10, 20, 30];. Read the second and third elements with add in an unsafe block; print both and the result of is_null() separated by spaces.

Starter code

main.rs
fn main() {
    // buraya yaz
}

Sample solution

main.rs
fn main() {
    let v = [10, 20, 30];
    let p = v.as_ptr();
    let (a, b) = unsafe { (*p.add(1), *p.add(2)) };
    println!("{} {} {}", a, b, p.is_null());
}

Expected output

20 30 false

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What is undefined behaviour (UB)?

  • A panic
  • A warning
  • A situation where the compiler gives no guarantees; the program may do anything Correct answer
  • A compile error

Explanation: UB sometimes appears to "work"; it can break when the optimization level or compiler version changes. The Miri tool helps catch UB.

2 Advance the pointer

Question
let p = v.as_ptr();
let ikinci = unsafe { *p.____(1) };
Answer
let p = v.as_ptr();
let ikinci = unsafe { *p.add(1) };

Explanation: add(n) advances the pointer by n elements.

3 Expression and safety

Term Meaning
v.as_ptr() Safe
p.is_null() Safe (check)
*p.add(1) unsafe
std::ptr::null() Null pointer

All lessons in Advanced