#include <iostream> 
#include <stdio.h> 
#include <string> 
 
struct  A
{ 
    A( const  std:: string &  pa)  :  a( pa)  { printf ( "CTR: A address: %p\n " , this )  ; } 
    std:: string  a; 
} ; 
 
struct  B
{ 
    B( const  std:: string &  pb)  :  b( pb)  { printf ( "CTR: B address: %p\n " , this )  ; } 
    std:: string  b; 
} ; 
 
// assumed data layout: 
struct  C { 
 
    C( )  :  a( "astring" ) , b( "bstring" )  { } 
  // ... 
  A a; 
  // ... 
  B b; 
} ; 
 
void  approach1(  A * pa, B * pb ) 
{ 
 
    printf ( "approach1: A address: %p B address: %p\n " , pa, pb) ;  
    // compute offset: 
    std:: ptrdiff_t  offset =  static_cast < char * > ( ( void * ) pb)  -  static_cast < char * > ( ( void * ) pa) ; 
    // then in some other function... 
    // given offset and ptr to b, compute ptr to a: 
    A * a =  static_cast < A* > (  ( void * ) ( static_cast < char * > ( ( void * ) pb)  +  offset)  ) ; 
    printf ( "approach1: a address: %p \n " , a) ;  
 
    std:: cout  <<  "approach1: A->a="  <<  a- > a <<  std:: endl ; 
} 
 
 
void  approach2(  A * pa, B * pb ) 
{ 
    printf ( "approach2: A address: %p B address: %p\n " , pa, pb) ;  
 
    std:: ptrdiff_t  offset =  reinterpret_cast < char * > ( pb)  -  reinterpret_cast < char * > ( pa) ; 
 
    A * a =  reinterpret_cast < A* > (  reinterpret_cast < char * > ( pb)  +  offset ) ; 
    printf ( "approach2: a address: %p \n " , a) ;  
    std:: cout  <<  "approach2: A->a="  <<  a- > a <<  std:: endl ; 
} 
 
main( ) 
{ 
  C c; 
  std:: cout  <<  c.a .a  <<  std:: endl ; 
 
  approach1( & c.a , & c.b ) ; 
  approach2( & c.a , & c.b ) ; 
} 
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN0cmluZz4KCnN0cnVjdCBBCnsKICAgIEEoY29uc3Qgc3RkOjpzdHJpbmcmIHBhKSA6IGEocGEpIHtwcmludGYoIkNUUjogQSBhZGRyZXNzOiAlcFxuIiwgdGhpcykgO30KICAgIHN0ZDo6c3RyaW5nIGE7Cn07CgpzdHJ1Y3QgQgp7CiAgICBCKGNvbnN0IHN0ZDo6c3RyaW5nJiBwYikgOiBiKHBiKSB7cHJpbnRmKCJDVFI6IEIgYWRkcmVzczogJXBcbiIsIHRoaXMpIDt9CiAgICBzdGQ6OnN0cmluZyBiOwp9OwoKLy8gYXNzdW1lZCBkYXRhIGxheW91dDoKc3RydWN0IEMgewoKICAgIEMoKSA6IGEoImFzdHJpbmciKSwgYigiYnN0cmluZyIpIHt9CiAgLy8gLi4uCiAgQSBhOwogIC8vIC4uLgogIEIgYjsKfTsKCnZvaWQgYXBwcm9hY2gxKCBBICpwYSwgQiAqcGIgKQp7CgogICAgcHJpbnRmKCJhcHByb2FjaDE6IEEgYWRkcmVzczogJXAgQiBhZGRyZXNzOiAlcFxuIiwgcGEsIHBiKTsgCiAgICAvLyBjb21wdXRlIG9mZnNldDoKICAgIHN0ZDo6cHRyZGlmZl90IG9mZnNldCA9IHN0YXRpY19jYXN0PGNoYXIqPigodm9pZCopcGIpIC0gc3RhdGljX2Nhc3Q8Y2hhcio+KCh2b2lkKilwYSk7CiAgICAvLyB0aGVuIGluIHNvbWUgb3RoZXIgZnVuY3Rpb24uLi4KICAgIC8vIGdpdmVuIG9mZnNldCBhbmQgcHRyIHRvIGIsIGNvbXB1dGUgcHRyIHRvIGE6CiAgICBBICphID0gc3RhdGljX2Nhc3Q8QSo+KCAodm9pZCopKHN0YXRpY19jYXN0PGNoYXIqPigodm9pZCopcGIpICsgb2Zmc2V0KSApOwogICAgcHJpbnRmKCJhcHByb2FjaDE6IGEgYWRkcmVzczogJXAgXG4iLCBhKTsgCgogICAgc3RkOjpjb3V0IDw8ICJhcHByb2FjaDE6IEEtPmE9IiA8PCBhLT5hIDw8IHN0ZDo6ZW5kbDsKfQoKCnZvaWQgYXBwcm9hY2gyKCBBICpwYSwgQiAqcGIgKQp7CiAgICBwcmludGYoImFwcHJvYWNoMjogQSBhZGRyZXNzOiAlcCBCIGFkZHJlc3M6ICVwXG4iLCBwYSwgcGIpOyAKCiAgICBzdGQ6OnB0cmRpZmZfdCBvZmZzZXQgPSByZWludGVycHJldF9jYXN0PGNoYXIqPihwYikgLSByZWludGVycHJldF9jYXN0PGNoYXIqPihwYSk7CiAgCiAgICBBICphID0gcmVpbnRlcnByZXRfY2FzdDxBKj4oIHJlaW50ZXJwcmV0X2Nhc3Q8Y2hhcio+KHBiKSArIG9mZnNldCApOwogICAgcHJpbnRmKCJhcHByb2FjaDI6IGEgYWRkcmVzczogJXAgXG4iLCBhKTsgCiAgICBzdGQ6OmNvdXQgPDwgImFwcHJvYWNoMjogQS0+YT0iIDw8IGEtPmEgPDwgc3RkOjplbmRsOwp9CgptYWluKCkKewogIEMgYzsKICBzdGQ6OmNvdXQgPDwgYy5hLmEgPDwgc3RkOjplbmRsOwoKICBhcHByb2FjaDEoJmMuYSwgJmMuYik7CiAgYXBwcm9hY2gyKCZjLmEsICZjLmIpOwp9