[comp.lang.c++] calculate member byte offset

ttwang@polyslo.CalPoly.EDU (Thomas Wang) (10/06/89)

I need to know the byte offset of 'header' in class 'foo' before any
'foo' object is allocated.

class foo
{
public:
  int grr;
  int header;
  void alloc();
};

void foo::alloc()
{
  cout << (&(this->header)) - this << "\n";   // bomb?
}

main()
{
  ((foo*) 0) -> alloc();   // bomb?
}

Just how portable is this kind of code?

 -Thomas Wang ("This is a fantastic comedy that Ataru and his wife Lum, an
                invader from space, cause excitement involving their neighbors."
                  - from a badly translated Urusei Yatsura poster)

                                                     ttwang@polyslo.calpoly.edu

jima@hplsla.HP.COM (Jim Adcock) (10/07/89)

>//Thomas Wang
>//I need to know the byte offset of 'header' in class 'foo' before any
>//'foo' object is allocated.

class foo
{
public:
  int grr;
  int header;		//does header stuff really need to be public?
  void alloc();
};

void foo::alloc()
{
  cout << (&(this->header)) - this << "\n";   // bomb! 2.0 complains that this
// is of type foo*, while &(this->header) is of type int*.  Maybe you can get
// away with coercing them both to type char*, but not guaranteed to work with
// all compilers
}

main()
{
  ((foo*) 0) -> alloc();   // bomb?  -- possible on a machine that
		  	   // disallows dereferencing a null pointer
}

haynes@wsl.dec.com (Charles Haynes) (10/08/89)

The (relatively gross) hack we used in the X Intrinsics is:

#define XtOffset(type,field)    ((unsigned int)&(((type)NULL)->field))

This has a different set of problems from your example, but works on most
architectures/compilers. Some "C"'s provide an offset builtin that you 
could use. As for the problems with your example:

> class foo
> {
> public:
>   int grr;
>   int header;		//does header stuff really need to be public?
>   void alloc();
> };
> 
> void foo::alloc()
> {
>   cout << (&(this->header)) - this << "\n";   // bomb! 2.0 complains 
> // that this is of type foo*, while &(this->header) is of type int*.
> // Maybe you can get away with coercing them both to type char*, but
> // not guaranteed to work with all compilers

That's right! You are subtracting things of different type. *I* wouldn't
expect it to work in general. This is where I'd use the XtOffset macro.

> }
> 
> main()
> {
>   ((foo*) 0) -> alloc();   // bomb?  -- possible on a machine that
> 		  	   // disallows dereferencing a null pointer

This should be possible on ANY machine. You aren't actually dereferencing
anything, you're just selecting a member function and passsing "this" to
it. "alloc" had better be ready to get a NULL "this" though.

> }

Hope this is helpful.

	-- Charles

jima@hplsla.HP.COM (Jim Adcock) (10/10/89)

>This should be possible on ANY machine. You aren't actually dereferencing
>anything, you're just selecting a member function and passsing "this" to
>it. "alloc" had better be ready to get a NULL "this" though.

Well, my 680x0 compiler does a "lea" "load effective address" based on
what you pass "alloc" --which is not quite actually dereferencing the pointer.
But I wonder if machines that trap on null pointers wouldn't actually trap
on their equivalent to "lea" ???