2016-10-28 3 views
3

Während rohe Zeiger in Rust die offset Methode haben, wird diese nur um die Größe des Zeigers erhöht. Wie kann ich auf den Zeiger in Bytes zugreifen?Wie bekomme ich den Zeiger-Offset in Bytes?

So etwas wie dies in C:

var_offset = (typeof(var))((char *)(var) + offset); 
+0

Haben Sie versucht, den Zeiger in einen Bytezeiger umzuwandeln? –

+0

versucht, aber Cast ist nicht erlaubt - '' Casting '& MyStruct' als' * const u8' ist ungültig''. – ideasman42

+0

Gut zu wissen, dass ich nicht der Einzige bin, der es versucht hat: D –

Antwort

7

Vom answer ich zu Ihrer vorherigen Frage verbunden:

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

Wir sind auf die Berechnung von p2 sehen können, dass ein Zeiger kann schmerzlos umgewandelt werden eine Ganzzahl (usize hier), auf der Arithmetik ausgeführt wird, und dann wird das Ergebnis an einen Zeiger zurückgegeben.

isize und usize die universellen Byte-Größe Zeigertypen sind :)

1

Dank @Matthieu M. Antwort kann dieser Zeiger Offsets tun, here eine wiederverwendbare Makro:

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

macro_rules! check_type_pair { 
    ($a:expr, $b:expr) => { 
     if false { 
      let _type_check = if false {$a} else {$b}; 
     } 
    } 
} 

macro_rules! parent_of_mut { 
    ($child:expr, $ty:ty, $field:ident) => { 
     { 
      check_type_pair!(&(*(0 as *const $ty)).$field, &$child); 
      let offset = offset_of!($ty, $field); 
      &mut *(((($child as *mut _) as usize) - offset) as *mut $ty) 
     } 
    } 
} 

macro_rules! parent_of { 
    ($child:expr, $ty:ty, $field:ident) => { 
     { 
      check_type_pair!(&(*(0 as *const $ty)).$field, &$child); 
      let offset = offset_of!($ty, $field); 
      &*(((($child as *const _) as usize) - offset) as *const $ty) 
     } 
    } 
} 

diese Weise, wenn wir ein Feld in einer Struktur haben, können wir die übergeordnete Struktur wie diese:

fn some_method(&self) { 
    // Where 'self' is ParentStruct.field, 
    // access ParentStruct instance. 
    let parent = unsafe { parent_of!(self, ParentStruct, field) }; 
} 

Das Makro check_type_pair hilft, einfache Fehler zu vermeiden, bei denen self und ParentStruct.field nicht vom selben Typ sind. Es ist jedoch nicht idiotensicher, wenn zwei verschiedene Mitglieder in einer Struktur den gleichen Typ haben.