如何在不运行代码的情况下验证 (repr(C)
) 结构的布局?例如。当我有
#[repr(C)]
struct Registers {
urxd: u32, // 0x00
_rsrvd0: [u32;15],
utxd: u32, // 0x40
_rsrvd1: [u32;15],
ucr1: u32, // 0x80
}
当 ucr1
不在位置 0x80 时(例如,由于错误计算的 _rsrvd
成员或取决于目标的填充),如何使构建过程失败?
在 C 语言中我会写类似的东西
struct foo {
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
};
static void _test() {
_Static_assert(offsetof(struct foo, d) == 12);
}
对于 _Static_assert
来说,似乎存在像 static_assertions
这样的包,它们实现了类似 C 时代的黑客技术(负数组大小等)。
但是对于 offsetof()
我只找到了非 const
实现。
代码适用于没有 #[test]
支持的嵌入式平台,因此我无法在运行时测试它。在 std 平台上运行 #[test]
可能会给出错误的结果,因为那里的填充/对齐方式不同。
最佳答案
您可以使用 const_field_offset
箱来获取偏移量,并使用 static_assertions
在构建期间进行断言。
use const_field_offset;
use static_assertions as sa;
#[repr(C)]
#[derive(const_field_offset::FieldOffsets)]
struct Registers {
urxd: u32, // 0x00
_rsrvd0: [u32;15],
utxd: u32, // 0x40
_rsrvd1: [u32;15],
ucr1: u32, // 0x80
}
sa::const_assert!(0x80 == Registers::FIELD_OFFSETS.ucr1.get_byte_offset());
当断言失败时,错误消息并不是很有帮助,但它至少会使构建失败:
sa::const_assert!(0x79 == Registers::FIELD_OFFSETS.ucr1.get_byte_offset());
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
关于unit-testing - 在构建时验证结构布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73652563/