015 Rust死靈書之Transmutes轉換

linghuyichong發表於2021-03-07

本系列錄製的影片主要放在B站上Rust死靈書學習影片

Rust 死靈書相關的原始碼資料在github.com/anonymousGiga/Rustonomi...

mem::transmute<T, U> 接受一個 T 型別的值,然後將它重新解析為型別 U。要求T和U的大小一樣。
這種操作是非安全的行為,可能產生未定義的行為。

1、位元組到型別轉換

u32::from_ne_bytes  從記憶體轉換到native位元組序列型別
u32::from_be_bytes 從記憶體轉換到大端序列型別
u32::from_le_bytes 從記憶體轉換到小端序列型別

2、transmute

pub const unsafe extern "rust-intrinsic" fn transmute<T, U>(e: T) -> U
將一種型別的值重新解釋為另一種型別。它將源值中的位複製到目標值中,然後忘記原始值。

例子:

//std::mem::transmute
//將連續的位元組轉換成另外一個型別,會產生為定義的行為

fn main() {
    //let raw_bytes = [0x78, 0x56, 0x34, 0x12];
    let mut raw_bytes = [0x78, 0x56, 0x34, 0x12];
    let num = unsafe {
        std::mem::transmute::<[u8; 4], u32>(raw_bytes)
    };
    let ret = u32::from_ne_bytes(raw_bytes);

    //assert_eq!(num, 0x12345678);
    assert_eq!(num, ret);
    println!("num = {}", num);
}

3、transmute_copy

pub unsafe fn transmute_copy<T, U>(src: &T) -> U
將src解釋為&U型別,然後讀取src的值。讀取時是建立副本,而不是直接移動。

例子:

use std::mem;

#[repr(packed)]
struct Foo {
    bar: u8,
}

fn main() {
    let foo_array = [10u8];

    unsafe {
        let mut foo_struct: Foo = mem::transmute_copy(&foo_array);
        assert_eq!(foo_struct.bar, 10);

        foo_struct.bar = 20;
        assert_eq!(foo_struct.bar, 20);
    }

    assert_eq!(foo_array, [10]);
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結
令狐一衝

相關文章