2016-08-07 6 views
2

私はタイプがあります。ポインタからメンバーへのポインタを含む構造体へのポインタの取得方法は?

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

を、私は知っているポインタがFoomemberBへのポインタです:

p: *const Baz 

を指す新しいポインタp: *const Fooを取得するための正しい方法は何ですか元の構造Foo

私の現在の実装では、私はかなり確信している、次が原因pFooへのポインタではありません(p as *const Foo)の間接参照に未定義の振る舞いを呼び出すです:

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

これは、FFIの一部です - Iこの操作を実行する必要がないようにコードを簡単に再構成することはできません。

これはGet pointer to object from pointer to some memberと非常によく似ていますが、私が知る限り、offsetofマクロはありません。

+0

は、なぜあなたはだけではなく、Cコードに '* constのFoo'に渡すことはできませんか? – Shepmaster

+0

この特定の例では、FFIは私に 'const Baz'を与えており、元のオブジェクトを取得することが期待されています。私が元のオブジェクトの周りを単に渡すことができれば、それは可能ですが、それは選択肢ではありません。 – Mystor

答えて

4

間接参照式は左辺値を生成しますが、実際にからを読んでいないという左辺値は、我々はそれにポインタ数学をやっているされているので、理論でが、それは十分に定義されなければなりません。それは私の解釈です。

私の解決策では、フィールドへのオフセットを取得するためにヌルポインタを使用する必要があります。したがって、1つの減算を避けるため、あなたのものよりも少し簡単です(0を減算します)。基本的に空ポインタからフィールドのアドレスを返すことによって、offsetofを実装しているCコンパイラ/標準ライブラリを見たと思います。これが、次の解決策に影響を与えたものです。

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!マクロ:

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); 
} 
関連する問題