pointers - 如何从原始指针创建一个 ?Sized 类型?

标签 pointers rust unsafe

下面是一个如何从原始指针转换 Sized 类型的示例:

use std::mem;

#[derive(Eq, PartialEq)]
#[repr(packed)]
struct Bob {
    id: u32,
    age: u32,
}

unsafe fn get_type<'a, T: Sized>(p: *const u8) -> &'a T {
    mem::transmute(p)
}

#[test]
fn it_works() {
    let bob = Bob {
        id: 22,
        age: 445,
    };
    let bob2: &Bob = unsafe {
        let ptr: *const u8 = mem::transmute(&bob);
        get_type(ptr)
    };
    assert_eq!(&bob, bob2);
}

但是,对于我的应用程序,我希望能够获得 ?Sized 类型而不是 Sized 类型。但是,这不起作用:

unsafe fn get_type2<'a, T: ?Sized>(p: *const u8) -> &'a T {
    mem::transmute(p)
}

失败并显示此错误消息:

error: transmute called with differently sized types: *const u8 (64 bits) to &'a T (pointer to T) [--explain E0512]
 --> src/main.rs:2:9
  |>
2 |>         mem::transmute(p)
  |>         ^^^^^^^^^^^^^^

我试图通过使用 std::slice::from_raw_parts 转换它来给它一个 &[u8](胖指针),但它几乎失败了同样的错误信息。

最佳答案

由于错误消息中引用的原因,您实际上不能。

Rust 引用可以是指针大小的(对于 Sized 类型)或更大(对于 !Sized 类型)。例如,如果 Trait 是一个特征,则 &Trait 引用实际上是两个字段,由 std::raw::TraitObject 定义。 .

因此,为了形成对未确定大小类型的引用,您必须:

  • 准确识别它是哪种类型的未调整大小的类型(特征?切片?...)
  • 选择正确的表示(std::raw::TraitObject, std::raw::Slice, ...)

然后你必须填写空白(不仅仅是一个指针)。

因此,除非您可以将函数限制为生成 &T where T: Sized,否则您不能只将原始指针转换为 &T

关于pointers - 如何从原始指针创建一个 ?Sized 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39186185/

相关文章:

c++ - 我应该使用 boost::ptr_vector<T> 还是 vector<boost::shared_ptr<T>>?

c - 将 for 循环中的字符串保存到 c 中的数组

c - 我无法理解这个区别

iterator - 仅删除符合条件的 Vec 的尾随元素

c# - 在 C# 中将十进制数组转换为字节数组,反之亦然

c# - 在循环内部或外部使用 unsafe 有什么区别吗?

JAVA 错误的变量引用?收到奇怪的输出 - 可能是内存地址?

rust - move 后改变结构的字段

serialization - 我如何反序列化为特征,而不是具体类型?

rust - 如何从原始指针获取数组或切片?