Question

Is there a better method to establish the positional offset of an object's data member than the following?

class object
{
  int a;
  char b;
  int c;
};

object * o = new object();
int offset = (unsigned char *)&(object->c) - (unsigned char *)o;
delete o;
Was it helpful?

Solution

In this case, your class is POD, so you can use the offsetof macro from <cstddef>.

In practice, in most implementations, for most classes, you can use the same trick which offsetof typically uses:

int offset = &(((object *)0)->c) - (object *)0;

No need to actually create an object, although you may have to fight off some compiler warnings because this is not guaranteed to work.

Beware also that if your class has any multiple inheritance, then for (at least) all but one base, (void*)(base*)some_object != (void*)(derived*)some_object. So you have to be careful what you apply the offset to. As long as you calculate and apply it relative to a pointer to the class that actually defines the field (that is, don't try to work out the offset of a base class field from a derived class pointer) you'll almost certainly be fine. There are no guarantees about object layout, but most implementations do it the obvious way.

Technically for any non-POD class, it does not make sense to talk about "the offset" of a field from the base pointer. The difference between the pointers is not required to be the same for all objects of that class.

OTHER TIPS

There's no need to actually create an object:

(size_t)&(((object*)0)->c)

That is, the address of a member in an object at address zero is the offset of that member into the object.

Of course, you will need access to the member, so you need to either make it a struct or add a public: access modifier.

This is how offsetof is implemented, at least for most compilers.

Rather than a pointer.
You can use a pointer to a member.

class X;
typedef int X::*    PtrToMemberInt;  // Declare a pointer to member.

class X
{
    int a;
    char b;
    float c;

    public:
    static PtrToMemberInt   getAPtr()
    {
        return &X::a;
    }

    int d;
};

int main()
{
    // For private members you need to use a public method to get the address.
    PtrToMemberInt aPtr = X::getAPtr();

    // For public members you can take the address directly;
    PtrToMemberInt dPtr = &X::d;


    // Use the pointer like this:
    X   a;
    a.*aPtr = 5;
    a.*dPtr = 6;
}

To add to Martins answer, as stated in "Design and Evolution of C++" by Stroustrup (section [13.11]):

pointers to data members have proven a useful way of expressing the layout of a C++ class in an implementation [Hübel, 1992]

Sandeep has been so kind as to convert the original paper and make it available on http://sandeep.files.wordpress.com/2008/07/ps.pdf

Note that the implementation described predated C++ RTTI, but I occasionally still use the pointer-to-member stuff.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top