我知道答案是“你不应该”...但是为了争论,你应该怎么做?
例如,如果您想编写 Vec<T>
的替代方案效果不同。
我看到你可以通过转换 * mut T
来制作“编译和运行的东西”值到 u64
并添加到它们中,然后将它们转化回 * mut T
并读取指针处的值(参见下面的示例)。它似乎有效,但它留下了一些悬而未决的问题:
请问
* mut T
指针总是适合u64
?是否
write()
当数据是来自libc:calloc
的任意(即非托管类型)数据 block 时,对不安全指针触发指针别名问题?这只适用于我使用原始类型 (
f64
)。如果这是一个真实的数据对象,我将不得不forget()
首先是对象;但你能简单地write()
一个* mut T
进入目标然后愉快地read()
如果类型复杂且有子记录,稍后再出来?这真的是正确的做法吗?显得格外别扭。我期待找到一些不安全的
ptrtoint()
/inttoptr()
对,但我找不到类似的东西。
例子
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
最佳答案
指针有一个 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
关于rust - 你应该如何在 Rust 中进行指针运算?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24759028/