【问题标题】:Why is `std::ptr::null` not usable with unsized types?为什么 `std::ptr::null` 不能用于未定义大小的类型?
【发布时间】:2019-12-20 14:24:30
【问题描述】:

据我了解,在 Rust 中创建空指针的标准(唯一?)方法是 std::ptr::null

但是,该函数声明如下。

pub const fn null<T>() -> *const T

在此声明中,T 被隐式假定为具有固定大小(否则为T: ?Sized)。因此,无法将此函数与 *const str*const [u32] 一起使用。 test it in the playground

排除未调整大小的类型是否有充分的理由?想要创建一个空的*const str 有什么问题?

【问题讨论】:

    标签: pointers rust


    【解决方案1】:

    一个指向非大小类型的指针是一个胖指针,它有两个组成部分:指针和类型元数据(切片的长度和特征对象的 vtable 指针;将来,Rust 可能允许其他类型的元数据)。 null 仅表示指针部分的值;其他值没有明显的选择。 (你可能认为 0 对于空切片指针的长度是显而易见的,我可以看到参数,但是如果指针为空,那么有多少东西就无关紧要了;无论如何你都不能取消引用它,所以要设置大小0 不是确保安全所必需的。)

    无法创建指向 trait 对象的空指针,但从 Rust 1.42 开始,您可以使用 ptr::slice_from_raw_parts 创建指向切片的空指针。假设切片的长度为0:

    use std::ptr;
    fn main() {
        let p: *const [u32] = ptr::slice_from_raw_parts(ptr::null(), 0);
        println!("{:?}", p);
    }
    

    没有与str 等效的函数,但您可以通过创建一个空的*const [u8] 并将其转换为as 来实现。

    这个函数(或相关的slice_from_raw_parts_mut)是可靠地创建指向切片的空指针的唯一方法。获取原始指针的常用方法是强制转换引用,但引用可能永远不会为空。

    【讨论】:

    • 有趣的是slice_from_raw_parts 是安全的——原因是它几乎无法使用,因为函数需要一个引用,而不是指针,并且unsafe 需要从一个指针转到另一个引用。跨度>
    • 空胖指针会有什么问题?您写道“[size] 没有明显的选择”,但相反,我会说 size 没有 wrong 值,因为大小对于空指针无关紧要...
    • @matthieu-m 同意,slice_from_raw_parts 可能会从“好”*const T 产生“错误”*const [T],如果提供的尺寸错误,所以我认为它应该被标记为不安全。 ..
    • @Pierre-Antoine:实际上,我同意不标记它unsafe。是的,它可以从一个好的*const T 产生一个错误的*const [T]...但是你不能使用没有unsafe*const [T] 将它转换为&amp;[T]&amp;mut [T]
    • @Pierre-Antoine 既然没有错误的长度,那么null应该返回什么长度呢?零?一?随意的东西?提供元数据暗示了一些取消引用指针的意图,这显然是错误的,所以我认为空切片指针(或空特征对象指针)可能是设计错误的结果。无论如何,您可能应该使用Option&lt;&amp;[T]&gt; 而不是*const [T]
    猜你喜欢
    • 1970-01-01
    • 2021-12-28
    • 2019-10-03
    • 2015-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-25
    相关资源
    最近更新 更多