mem::transmute() 函数
这个函数用于将一个值从当前类型转换成另一种类型. 类似于C语言中的强制类型转换. 要注意的是, 源类型与目标类型应该大小相同.
use std::mem;
fn main() {
let pack: [u8; 4] = [0x01, 0x02, 0x03, 0x04];
#[allow(unnecessary_transmutes)]
let pack_u32 = unsafe { mem::transmute::<[u8; 4], u32>(pack) };
assert_eq!(pack_u32, 0x04030201);
}
相同的功能, 用C语言实现:
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
int main() {
uint8_t pack[4] = {0x01, 0x02, 0x03, 0x04};
uint32_t pack_u32 = *(uint32_t*)pack;
assert(pack_u32 == 0x04030201);
return 0;
}
将枚举转换为 u8
用这个函数也可以将枚举结构中的签标 tag 值转为 u8 或者别的整数类型:
use std::mem;
#[derive(Debug, Clone, Copy)]
pub enum Shape {
Rectangle,
Circle,
Ellipse,
}
impl Shape {
pub fn tag(&self) -> u8 {
unsafe { mem::transmute(*self) }
}
}
fn main() {
let c = Shape::Circle;
println!("c.tag() is {}", c.tag());
}
手动构造切片引用
切片引用本身就是一个胖指针:
- data ptr: 指向切片元素的起始内存
- len: 切片中元素的个数
use std::mem;
fn main() {
let nums = [0_i32, 1, 2, 3];
let slice: &[i32] = unsafe {
let nums_addr: usize = nums.as_ptr() as usize;
let len = nums.len();
mem::transmute([nums_addr, len])
};
assert_eq!(slice.len(), 4);
assert_eq!(slice[2], 2);
assert_eq!(slice[3], 3);
}