https://google.github.io/comprehensive-rust/
https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer

TODO :

  • automatic dereference
  • concurrency
  • smart pointer

Cheatsheet

&T      &mut T      Type: shared / mutable reference to type T
&       &mut        Operator: make a (mutable) reference value
*                   Operator: dereferences
*const T            Raw pointer to immutable T
*mut T              Raw pointer to mutable T

Reference

#![allow(unused)]
fn main() {
/// reference provides way to access another value without takine responsibility
/// for the value aka. borrowing. Shared references are read-only and the
/// referenced data cannot change.
fn shared_references() {
    let a = 'A';
    let b = 'B';
    let mut r: &char = &a;
    println!("r: {}", *r);
    r = &b;
    // a mutable reference be changed to point to other data
    // but the refrenced data itself cannot change in this case.
    // DIFFERENT than C++ !!
    // shared reference does NOT allow modifying the value it refers to,
    // EVEN IF the value is mutable
    println!("r: {}", *r);
    
    // auto dereferences: use *r or r are the same.
    println!("r: {}", r);
}

/// exclusive aka mutable references, allow changing the value they refer to.
/// they have type &mut T
/// differentiate the two:
///     let mut x_coord: &i32
///     let mut x_coord: &mut i32
fn exclusive_references() {
    // &mut T   a exclusive (mutable) reference to type T
    // NO other (shared or exclusive) reference can exist at the same time
    // the referenced value cannot be accessed while the exclusive reference
    // exists
    let mut point = (1, 2);
    let x_coord = &mut point.0;
    *x_coord = 20;
    // point.0 = 0;         // this is illegal while x_coord is alive
    println!("point: {point:?}");
}

}

Smart Pointers

TODO finish this

Raw Pointers

#![allow(unused)]
fn main() {
fn raw_pointer() {
    let mut num:i32 = 5;
    // declaring raw pointers is safe.
    let ptr1 = &mut num as *mut i32;
    let ptr2 = &mut num as *mut i32; // both are valid pointer to 
    // dereferencing raw pointers is unsafe
    unsafe {
        *ptr1 += 1;
        *ptr2 += 1;
    }
    println!("{}", num); // 7

    let num:i32 = 5;
    // illegal because num is not mutable
    let ptr3 = &mut num as *mut i32;
    // illegal because the different type
    let ptr3 = &num as *const u32;
    // "legal" cast with indirection
    let ptr = &(r as u32) as *const u32;
    // casting and reading is legal
    let ptr_mut = ptr as *mut u32;
    // but dereferencing is illega even in unsafe
    // TODO learn UnsafeCell
    unsafe{
        println!("{}", *ptr_mut);
        *ptr_mut ++;
        println!("{}", *ptr_mut);
    }
    // cast raw value into raw pointer:
    let addr:usize = 0xffff40;
    let wtf = unsafe{*(addr as *const u64)};
    println!("{}", wtf);    // segfault
    // TODO I think it's hackable to cast an address to usize,
    // then cast it to whatever you want. But it turns out that
    // &T as usize is illegal... are there other hacks?

}
}