Pass raw pointer without copying

Hello Rustaceans! How can I pass a raw pointer without copying?
For example,

fn increment(mut ptr: *mut u8) {
    ptr = unsafe { ptr.add(1) };
}

let mut arr: [u8; 3] = [b'a'; 3];
let mut ptr = arr.as_mut_ptr();

println!("{:p}", ptr); // 0x7fff8dd996ad
increment(ptr);
println!("{:p}", ptr); // 0x7fff8dd996ad, but i want 0x7fff8dd996ae

Rust has pass-by-reference by using a reference - surprise, surprise.

fn increment(ptr: &mut *mut u8) {
    *ptr = unsafe { ptr.add(1) };
}
2 Likes
fn increment(ptr: &mut *mut u8) {
    *ptr = unsafe { ptr.add(1) };
}

fn main() {
    
    let mut arr: [u8; 3] = [b'a'; 3];
    let mut ptr = arr.as_mut_ptr();
    
    println!("{:p}", ptr); // 0x7fff8dd996ad
    increment(&mut ptr);
    println!("{:p}", ptr); // 0x7fff8dd996ad, but i want 0x7fff8dd996ae
}

(Playground)

Output:

0x7ffc37dc03fd
0x7ffc37dc03fe

1 Like

The mut specifier on function parameters doesn't mean that you pass a value by reference and mutate it. Rust never does it. All arguments are always passed by move. The mut specifier just means that you can mutate the corresponding local variable within the function. Without an explicit mut, local variables are always immutable (sans types with interior mutability).

Your function declaration is equivalent to the following:

fn increment(ptr: *mut u8) {
    let mut ptr = ptr;
    ptr = unsafe { ptr.add(1) };
}

Which makes it obvious why the caller's value wasn't mutated.

If you want to mutate an external value, you need to pass it explicitly as a &mut, and correspondingly create a &mut ptr at the call site, as @jbe shows in the example.

3 Likes