You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在编译时验证Rust中repr(C)结构体的内存布局?

Rust中验证repr(C)结构体内存布局的静态断言方案

你可以通过以下几种方式在编译阶段验证#[repr(C)]结构体的成员偏移量,无需运行代码:

1. 自定义const偏移量函数+静态断言

Rust 1.64及以上版本支持在const函数中计算结构体成员偏移量,结合static_assertions crate的const_assert宏实现编译时检查:

首先在Cargo.toml添加依赖:

[dependencies]
static_assertions = "1.1"

然后编写验证代码:

use static_assertions::const_assert;

#[repr(C)]
struct Registers {
    urxd:       u32,        // 0x00
    _rsrvd0:    [u32;15],
    utxd:       u32,        // 0x40
    _rsrvd1:    [u32;15],
    ucr1:       u32,        // 0x80
}

// 自定义const上下文的偏移量计算函数
const fn offset_of<T, U>(_: &T, field: unsafe fn(&T) -> &U) -> usize {
    unsafe { (field(&*(0 as *const T)) as *const U) as usize }
}

// 编译阶段断言ucr1的偏移量必须为0x80
const_assert!(offset_of(&Registers, |r| &r.ucr1) == 0x80);

这个offset_of函数完全在编译期完成计算,不会产生任何运行时开销,且适配嵌入式平台的编译目标。

2. 使用标准库内置的core::mem::offset_of(Rust 1.79+)

Rust 1.79版本正式稳定了标准库的core::mem::offset_of const函数,无需手动实现偏移量计算:

use static_assertions::const_assert;
use core::mem::offset_of;

#[repr(C)]
struct Registers {
    urxd:       u32,        // 0x00
    _rsrvd0:    [u32;15],
    utxd:       u32,        // 0x40
    _rsrvd1:    [u32;15],
    ucr1:       u32,        // 0x80
}

const_assert!(offset_of!(Registers, ucr1) == 0x80);

这种方式更简洁,直接依赖标准库即可完成验证。

3. 补充验证结构体总大小

除了单个成员的偏移量,还可以验证结构体总大小,避免平台自动填充导致的布局错误:

const_assert!(core::mem::size_of::<Registers>() == 0x84); // ucr1占4字节,总大小为0x80+0x4

适配旧工具链方案

如果你的嵌入式平台使用Rust 1.64以下版本的工具链,可以使用memoffset crate的const_offset_of宏:

[dependencies]
memoffset = { version = "0.9", features = ["const_offset_of"] }
use static_assertions::const_assert;
use memoffset::const_offset_of;

const_assert!(const_offset_of!(Registers, ucr1) == 0x80);

关键注意事项

  • 必须确保编译目标与嵌入式平台一致(通过Cargo.toml指定目标三元组),避免因不同平台的对齐规则差异导致检查结果失真。

内容的提问来源于stack exchange,提问作者ensc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 05:55:23