简体   繁体   中英

How would I write this C function in Rust?

How would I write the function below in Rust? Is there a way to write replace() safely or is the operation inherently unsafe? list does not have to be an array, a vector would work as well. It's the replacement operation that I'm interested in.

void replace(int *list[], int a, int b) {
    *list[a] = *list[b];
}

I would like the following behavior:

int a = 1;
int b = 2;
int *list[] = { &a, &a, &b, &b };

*list[0] = 3;        // list has pointers to values: [3, 3, 2, 2]
replace(list, 2, 0); // list has pointers to values: [3, 3, 3, 3]
*list[0] = 4;        // list has pointers to values: [4, 4, 4, 4]

Answer for modified question

Rust does not allow you to have multiple mutable references ( aliasing ) to the same item. This means you'd never be able to run the equivalent of your third line:

fn main() {
    let mut a = 1;
    let vals = &[&mut a, &mut a];
}

This fails with:

cannot borrow `a` as mutable more than once at a time

What about using Rc and RefCell?

Rc doesn't let us mutate the value:

A reference-counted pointer type over an immutable value .

(Emphasis mine)

RefCell::borrow_mut won't allow multiple concurrent borrows:

Panics if the value is currently borrowed.

Answer for original question

It's basically the same. I picked a u8 cause it's easier to type. :-)

fn replace(v: &mut [&mut u8], a: usize, b: usize) {
    *v[a] = *v[b]
}

fn main() {
    let mut vals = vec![1,2,3,4];
    {
        let mut val_refs: Vec<&mut u8> = vals.iter_mut().collect();
        replace(&mut val_refs, 0, 3);
    }
    println!("{:?}", vals);
}

( playpen link )

Rust does do boundary-checking, so if you call with an index bigger than the slice, the program will panic and you don't get memory corruption.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM