对于struct成员,可以计算Rust中的offsetof
,类似于C' offsetof
。
虽然这适用于struct字段,但我无法找到与枚举及其变体成员相同的方法。
通过与IRC上的开发人员交谈,不能保证枚举的所有成员都是一致的:
如何计算枚举成员的偏移量?
对于实例,它可以像这样工作:
enum Test { A(u8), B(f64) };
fn test_me(a: Test) {
if let Test::A(b) = a {
// we could find the offset between 'a' and 'b' here.
// but how to do this without instantiating variables?
println("{}", (b as *const _) as usize - (a as *const _) as usize);
}
}
然而,目标是能够通过仅检查类型来完成此操作,因此它可以编译为常量,例如:
println("{}", offset_of_enum!(Test, A));
在尝试为此编写宏时,我遇到了::
加入参数的问题,因此我不确定如何解决该部分。
答案 0 :(得分:4)
Enum变体与struct字段有很大不同。枚举变体不具有与枚举类型不同的唯一类型。甚至在Rust编译器内部,枚举变量也包括枚举的判别式。这意味着enum变量对枚举本身的偏移量为零。
您更希望获得枚举变体字段的偏移量。由于获取枚举变量字段引用的唯一方法是匹配枚举值,因此您需要一个有效的枚举值来匹配,因此您无法使用在struct field offset计算中使用的nullpointer技巧。
macro_rules! offset_of {
($($tt:tt)*) => {
{
let base = $($tt)*(unsafe { ::std::mem::uninitialized() });
let offset = match base {
$($tt)*(ref inner) => (inner as *const _ as usize) - (&base as *const _ as usize),
_ => unreachable!(),
};
::std::mem::forget(base);
offset
}
}
}
enum Foo {
A(i32),
B(u8),
}
let offset = offset_of!(Foo::A);
由读者为枚举结构变体和具有多个字段的枚举变体实现此宏。