如何从指向成员的指针获取指向包含结构的指针? [英] How to get a pointer to a containing struct from a pointer to a member?

查看:104
本文介绍了如何从指向成员的指针获取指向包含结构的指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类型:

struct Foo {
    memberA: Bar,
    memberB: Baz,
}

和一个我知道的指针,它是指向Foo中的memberB的指针:

and a pointer which I know is a pointer to memberB in Foo:

p: *const Baz

获取指向原始结构Foo的新指针p: *const Foo的正确方法是什么?

What is the correct way to get a new pointer p: *const Foo which points to the original struct Foo?

我当前的实现如下,由于(p as *const Foo)的取消引用,我很确定会调用未定义的行为,其中p不是指向Foo的指针:

My current implementation is the following, which I'm pretty sure invokes undefined behavior due to the dereference of (p as *const Foo) where p is not a pointer to a Foo:

let p2 = p as usize -
    ((&(*(p as *const Foo)).memberB as *const _ as usize) - (p as usize));

这是FFI的一部分-为了避免需要执行此操作,我无法轻松地重组代码.

This is part of FFI - I can't easily restructure the code to avoid needing to perform this operation.

这非常类似于从指针获取指向对象的指针,但对于Rust,据我所知,它没有offsetof宏.

This is very similar to Get pointer to object from pointer to some member but for Rust, which as far as I know has no offsetof macro.

推荐答案

解引用表达式会产生一个左值,但实际上不是从中读取该左值,我们只是在对它进行指针数学运算,因此,理论上,应该对其进行明确定义.不过那只是我的解释.

The dereference expression produces an lvalue, but that lvalue is not actually read from, we're just doing pointer math on it, so in theory, it should be well defined. That's just my interpretation though.

我的解决方案涉及使用空指针检索到字段的偏移量,因此它比您的偏移量简单一些,因为它避免了减法(我们将减去0).我相信我看到一些C编译器/标准库通过本质上从空指针返回字段地址来实现offsetof,这正是以下解决方案的灵感.

My solution involves using a null pointer to retrieve the offset to the field, so it's a bit simpler than yours as it avoids one subtraction (we'd be subtracting 0). I believe I saw some C compilers/standard libraries implementing offsetof by essentially returning the address of a field from a null pointer, which is what inspired the following solution.

fn main() {
    let p: *const Baz = 0x1248 as *const _;
    let p2: *const Foo = unsafe { ((p as usize) - (&(*(0 as *const Foo)).memberB as *const _ as usize)) as *const _ };
    println!("{:p}", p2);
}

我们还可以定义自己的offset_of!宏:

We can also define our own offset_of! macro:

macro_rules! offset_of {
    ($ty:ty, $field:ident) => {
        unsafe { &(*(0 as *const $ty)).$field as *const _ as usize }
    }
}

fn main() {
    let p: *const Baz = 0x1248 as *const _;
    let p2: *const Foo = ((p as usize) - offset_of!(Foo, memberB)) as *const _;
    println!("{:p}", p2);
}

这篇关于如何从指向成员的指针获取指向包含结构的指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆