你应该怎么在Rust中做指针算术?

时间:2014-07-15 13:06:49

标签: rust

我知道答案是“你不应该”......但是为了争论,应该如何你做到了?

例如,如果您想编写一种替代Vec<T>的替代方法,那就是

我发现您可以通过将* mut T值转换为u64并添加到* mut T中,然后将它们转换回* mut T并读取值来创建“可编译和运行的内容”指针(见下面的例子)。它似乎有效,但它留下了一些悬而未决的问题:

  1. u64指针是否始终适合write()

  2. 当数据是来自libc:calloc的任意(即非托管类型)数据块时,f64是否发生不安全指针触发指针别名问题?

  3. 这只能起作用,因为我使用的是原始类型(forget())。如果这是一个真正的数据对象,我必须先write()该对象;但是,如果类型很复杂并且有子记录,你可以简单地* mut T read() ptrtoint()进入目标,然后再愉快地inttoptr()出来吗?

  4. 这真的是这样做的正确方法吗?这看起来非常尴尬。我期待找到一些不安全的extern crate libc; use std::mem::size_of; use std::ptr::write; use std::ptr::read; use std::mem::transmute; use libc::calloc; use libc::free; use libc::c_void; struct Array { length: usize, data: *mut f64, } impl Array { fn new(length: usize) -> Array { unsafe { Array { length: length, data: calloc(size_of::<f64>(), length) as *mut f64, } } } fn set(&mut self, offset: usize, value: f64) { if offset < self.length { unsafe { let root: *mut f64 = transmute(transmute::<*mut f64, u64>(self.data) + (size_of::<f64>() * offset) as u64); println!("Write: [{:?}] -> {}", root, value); write(root, value); } } else { println!("Write: Nope: [{}] is out of bounds", offset); } } fn get(&self, offset: usize) -> f64 { if offset < self.length { unsafe { let root: *const f64 = transmute(transmute::<*mut f64, u64>(self.data) + (size_of::<f64>() * offset) as u64); let rtn = read::<f64>(root); println!("Read: [{:?}] -> {}", root, rtn); return rtn; } } println!("Read: Nope: [{}] is out of bounds", offset); 0.0 } } impl Drop for Array { fn drop(&mut self) { unsafe { free(self.data as *mut c_void); } } } fn main() { let mut tmp = Array::new(4); tmp.set(0, 100.5); tmp.set(1, 101.5); tmp.set(2, 102.5); tmp.set(3, 103.5); tmp.set(4, 104.5); tmp.get(0); tmp.get(1); tmp.get(2); tmp.get(3); tmp.get(4); } / Write: [0x7f04bdc1e080] -> 100.5 Write: [0x7f04bdc1e088] -> 101.5 Write: [0x7f04bdc1e090] -> 102.5 Write: [0x7f04bdc1e098] -> 103.5 Write: Nope: [4] is out of bounds Read: [0x7f04bdc1e080] -> 100.5 Read: [0x7f04bdc1e088] -> 101.5 Read: [0x7f04bdc1e090] -> 102.5 Read: [0x7f04bdc1e098] -> 103.5 Read: Nope: [4] is out of bounds 对,但我找不到那样的东西。

  5. 实施例

    {{1}}

    输出

    {{1}}

1 个答案:

答案 0 :(得分:43)

指针有指针运算的offset method

fn main() {
    let items = [1usize, 2, 3, 4];

    let ptr = &items[1] as *const usize;

    println!("{}", unsafe { *ptr });
    println!("{}", unsafe { *ptr.offset(-1) });
    println!("{}", unsafe { *ptr.offset(1) });
}

输出

2
1
3

https://doc.rust-lang.org/nightly/book/first-edition/unsafe.html

相关问题