将指针的值存储在Rust中的另一个指针中

时间:2018-03-07 02:50:28

标签: pointers rust

将指针存储为另一个指针的值的最佳方法是什么?

我有一个ptr类型的变量*mut u8。如何将ptr指向的地址存储为同样为[{1}}类型的另一个指针t的值。

我正在尝试做类似

的事情
*mut u8

我收到*t = ptr; 错误。我知道地址expected u8, found *-ptr将是64位。我想从地址ptr开始填充64位。

2 个答案:

答案 0 :(得分:6)

  

我有一个ptr类型的变量*mut u8。如何将ptr指向的地址存储为另一个指针t的值*mut u8

将一个指针指向另一个:

use std::ptr;

fn main() {
    let ptr: *mut u8 = ptr::null_mut();
    let t: *mut u8 = ptr;
}

ptr是一个指针,它指向的地址是NULL。此值现在存储在与t相同类型的指针ptr中:t指向地址NULL

+-----+        +-----+
|     |        |     |
| ptr |        |  t  |
|     |        |     |
+--+--+        +--+--+
   |              |
   |              |
   +---->NULL<----+

如果您希望t成为指向另一个指针地址的指针,则需要引用ptr。类型也可能不一样:

use std::ptr;

fn main() {
    let ptr: *mut u8 = ptr::null_mut();
    let t: *const *mut u8 = &ptr;
}
+-----+      +-----+
|     |      |     |
|  t  +------> ptr +----->NULL
|     |      |     |
+-----+      +-----+
  

我正在寻找一种方法来将ptr指向的地址写入特定位置,这样即使我没有t

,我也可以获取地址

原始指针没有与它们相关联的编译器强制生命周期。如果你想在值消失后保留某些东西的地址,这对他们来说是理想的情况 - 你不需要做任何事情:

use std::ptr;

fn do_not_dereference_this_result() -> *const u8 {
    let val: u8 = 127;
    let ptr: *const u8 = &val;
    ptr
}

fn main() {
    println!("{:p}", do_not_dereference_this_result())
}

在极少数情况下,您可能希望将地址存储在usize(指针大小的整数值)中:

use std::ptr;

fn do_not_dereference_this_result() -> usize {
    let val: u8 = 127;
    let ptr: *const u8 = &val;
    ptr as usize
}

fn main() {
    println!("{:x}", do_not_dereference_this_result())
}

真的听起来像你对指针的工作方式感到困惑,这是一个很好的迹象,如果你使用它们,你将会自己开枪。我强烈鼓励您在任何重要代码中单独使用引用,直到您对指针的理解增加为止。

答案 1 :(得分:-1)

你通常不想这样做,但我相信你知道你在做什么。

这里的关键是了解一些事情:

  • Box<T>大致相当于在堆上分配的*T,您可以使用Box::into_raw将其转换为*T

    < / LI>
  • 如果你这样做,你就会有效地泄漏分配了Box<T>的堆,因为Rust不再知道它在哪里,或者跟踪它。您必须在某个时刻手动将其转换回可放置的对象,例如使用Box::from_raw

  • 必须 Box::new(...)一个值,以确保它被放在堆上,否则你的原始指针将指向堆栈,最终将变为无效。

  • 可变别名(意味着指向同一数据的两个&mut T)会导致未定义的行为。非常重要的是要理解未定义的行为不是由并发写入触发到可变别名......它由mutable aliases existing at the same time, in any scope触发。

...但是,如果你真的想,你会这样做:

let foo_ref = Box::into_raw(Box::new(10));
let foo_ref_ref =  Box::into_raw(Box::new(foo_ref));

// Modify via raw pointer
unsafe {
    **(foo_ref_ref as *const *mut i32) = 100;
}

// Read via raw pointer 
unsafe {
    println!("{:?}", **foo_ref_ref);
}

// Resolve leaked memory
unsafe {
    Box::from_raw(foo_ref_ref);
    Box::from_raw(foo_ref);
}