Rust从入门到实战系列三百零三:Deref 特征

Deref 特征在智能指针 - Deref章节中有更加详细的介绍。
transmute
std::mem::transmute 是一个 unsafe 函数,可以把一个类型按位解释为另一个类型,其中这两个类型必
须有同样的位数( bits )。
transmute 相当于将一个类型按位移动到另一个类型,它会将源值的所有位拷贝到目标值中,然后遗忘源
值。该函数跟 C 语言中的 memcpy 函数类似。
正因为此, transmute 非常非常不安全! 调用者必须要自己保证代码的安全性,当然这也是 unsafe 的目
的。
示例

  1. transmute 可以将一个指针转换成一个函数指针,该转换并不具备可移植性,原因是在不同机器
    上,函数指针和数据指针可能有不同的位数( size )。
    fn foo() -> i32 {
    0
    }
    fn main() {
    let pointer = foo as *const ();
    let function = unsafe {
    std::mem::transmute::<*const (), fn() -> i32>(pointer)
    };
    assert_eq!(function(), 0);
    }
  2. transmute 还可以扩展或缩短一个不变量的生命周期,将 Unsafe Rust 的不安全性体现的淋漓尽致!
    struct R<'a>(&'a i32);
    unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> {
    std::mem::transmute::<R<'b>, R<'static>>®
    }
    unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>)
    -> &'b mut R<'c> {
    std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>®
    }
  3. 事实上我们还可以使用一些安全的方法来替代 transmute .
    fn main() {
    /*Turning raw bytes(&[u8]) to u32, f64, etc.: */
    let raw_bytes = [0x78, 0x56, 0x34, 0x12];
    let num = unsafe { std::mem::transmute::<[u8; 4], u32>(raw_bytes) };
    // use u32::from_ne_bytes instead
    let num = u32::from_ne_bytes(raw_bytes);
    // or use u32::from_le_bytes or u32::from_be_bytes to specify the endianness
    let num = u32::from_le_bytes(raw_bytes);
    assert_eq!(num, 0x12345678);
    let num = u32::from_be_bytes(raw_bytes);
    assert_eq!(num, 0x78563412);
    /*Turning a pointer into a usize: */
    let ptr = &0;
    let ptr_num_transmute = unsafe { std::mem::transmute::<&i32, usize>(ptr) };
    // Use an as cast instead
    let ptr_num_cast = ptr as *const i32 as usize;
    /*Turning an &mut T into an &mut U: */
    let ptr = &mut 0;
    let val_transmuted = unsafe { std::mem::transmute::<&mut i32, &mut u32>(ptr) };
    // Now, put together as and reborrowing - note the chaining of as
    // as is not transitive
    let val_casts = unsafe { &mut *(ptr as *mut i32 as *mut u32) };
    /*Turning an &str into a &[u8]: */
    // this is not a good way to do this.
    let slice = unsafe { std::mem::transmute::<&str, &[u8]>(“Rust”) };
    assert_eq!(slice, &[82, 117, 115, 116]);
    // You could use str::as_bytes
    let slice = “Rust”.as_bytes();
    assert_eq!(slice, &[82, 117, 115, 116]);
    // Or, just use a byte string, if you have control over the string
    // Or, just use a byte string, if you have control over the string
    // literal
    assert_eq!(b"Rust", &[82, 117, 115, 116]);
    }
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值