Pointers 如何获取枚举成员的指针偏移量(以字节为单位)?

Pointers 如何获取枚举成员的指针偏移量(以字节为单位)?,pointers,rust,Pointers,Rust,对于结构成员,可以计算锈蚀,类似于C的偏移量 虽然这适用于结构字段,但我找不到一个等效的方法来处理枚举及其变体成员 与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 '

对于结构成员,可以计算锈蚀,类似于C的偏移量

虽然这适用于结构字段,但我找不到一个等效的方法来处理枚举及其变体成员

与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));


在尝试为此编写宏时,我遇到了通过以下方式连接参数的问题::,因此我不确定如何解决该部分。

枚举变量与结构字段有很大不同。枚举变量没有与枚举类型不同的唯一类型。即使在Rust编译器内部,也会表示枚举变量,包括枚举的判别式。这意味着枚举变量到枚举本身的偏移量为零

更可能需要枚举变量字段的偏移量。由于获取枚举变量字段引用的唯一方法是匹配枚举的值,因此需要有效的枚举值进行匹配,因此不能使用结构字段偏移量计算中使用的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);

对于包含多个字段的枚举结构变量和枚举元组变量,由读者来实现此宏。

我认为您的宏中缺少了一个
std::mem::forget
,可以丢弃
base
;不希望在未初始化的内存上执行
Drop
。测试这一点的一个简单方法是将
字符串
放入
a
中,并对
的内存进行置乱(例如,使用
0x8F
对其进行memset)。它似乎不适用于具有多个字段的枚举。我在match中添加了
,..
,这对单个字段和多个字段都有效,但是多个字段的初始化失败,并且不清楚如何处理:(是的,您需要在宏调用中给出枚举变量有多少字段的提示。据我所知,这是不可能解决的。只是在实际使用中进行了测试,效果很好。此外,还进行了双重检查,这将编译为具有优化构建的常量(无实际
std::mem
use)。可能会这样假设,但很高兴确认。为什么需要这样做?除了出于好奇之外,想要这样做似乎很奇怪。要访问包含枚举的结构。它直接用于具有一些常规信息的结构,可以方便地包含在调试/警告消息中,否则不是必需的。(该结构是只读的,因此在这种情况下应该是安全的)。那么您可以从对枚举的引用或对变量成员的引用开始吗?如果它是第一个,那么您根本不需要它。如果是后者,我会首先尝试找到一种不同的方法来解决它。@ker,它的变量成员,更新了问题。