短小精悍(3) - Rust结构体offset计算库memoffset介绍
今天给大家带来的是另一个“短小精悍”的库:memoffset
。经常和C语言打交道的同学肯定不会对C风格的结构体陌生,而在操作硬件设备、进行系统级编程时,直接从内存地址读/写结构体更是家常便饭。memoffset
就是一个用于帮助我们“精细”操作结构体的工具,它可以计算指定字段在结构体中的偏移量,从而帮助我们手动操作结构体的内存。
简介
memoffset
提供的宏offset_of
和C的宏offsetof很像,都可以计算一个结构成员相对于结构开头的字节偏移量,例如以下这个来自文档的示例:
use memoffset::offset_of;
#[repr(C, packed)]
struct Foo {
a: u32,
b: u32,
c: [u8; 5],
d: u32,
}
fn main() {
assert_eq!(offset_of!(Foo, b), 4);
assert_eq!(offset_of!(Foo, d), 4+4+5);
}
memoffset
还提供另一个用于获取内存范围的宏:span_of
。顾名思义,span_of
可以获取一个变量所位于的内存范围,例如这个来自于文档的示例:
use memoffset::span_of;
#[repr(C, packed)]
struct Foo {
a: u32,
b: u32,
c: [u8; 5],
d: u32,
}
fn main() {
assert_eq!(span_of!(Foo, a), 0..4);
assert_eq!(span_of!(Foo, a .. c), 0..8);
assert_eq!(span_of!(Foo, a ..= c), 0..13);
assert_eq!(span_of!(Foo, ..= d), 0..17);
assert_eq!(span_of!(Foo, b ..), 4..17);
}
案例
我们来看看memoffset
的使用案例。
NTFS库
NTFS
是一个用 Rust 实现的低级NTFS文件系统库。像它这样的库可能并不太喜欢特别频繁地进行大块的读写,但又不太方便直接把整个结构体从裸指针加载上来(这样做有违Rust库的身份),就可以考虑用memoffset来指向性地读取部分内容。例如:
#[repr(C, packed)]
pub(crate) struct RecordHeader {
signature: [u8; 4],
update_sequence_offset: u16,
update_sequence_count: u16,
logfile_sequence_number: u64,
}
#[derive(Clone, Debug)]
pub(crate) struct Record {
data: Vec<u8>,
position: NtfsPosition,
}
impl Record {
fn update_sequence_offset(&self) -> u16 {
let start = offset_of!(RecordHeader, update_sequence_offset);
LittleEndian::read_u16(&self.data[start..])
}
}
这是节选自ntfs/src/record.rs
的一段代码。可以看到,作者使用offset_of
宏来直接“精准”地从内存中读取了一个u16。我水平有限,但是我认为这样做可能是出于减少磁盘读写的目的,如果读者了解个中缘由可以留言赐教。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!