Search code examples
c++visual-c++

Data member offset in C++


"Inside the C++ Object Model" says that the offset of a data member in a class is always 1 more than the actual offset in order to distinguish between the pointer to 0 and the pointer to the first data member, here is the example:

class Point3d {
public:
     virtual ~Point3d();

public:
    static Point3d origin;
    float x, y, z;
};
//to be used after, ignore it for the first question
int main(void) {        
    /*cout << "&Point3d::x = " << &Point3d::x << endl;
    cout << "&Point3d::y = " << &Point3d::y << endl;
    cout << "&Point3d::z = " << &Point3d::z << endl;*/
    printf("&Point3d::x = %p\n", &Point3d::x);
    printf("&Point3d::y = %p\n", &Point3d::y);
    printf("&Point3d::z = %p\n", &Point3d::z);
    getchar();
}

So in order to distinguish the two pointers below, the offset of a data member is always 1 more.

float Point3d::*p1 = 0;
float Point3d::*p2 = &Point3d::x;

The main function above is attempt to get the offset of the members to verify this argument, which is supposed to output: 5, 9, 13(Consider the vptr of 4bytes at the beginning). In MS Visual Studio 2012 however, the output is:

&Point3d::x = 00000004
&Point3d::y = 00000008
&Point3d::z = 0000000C

Question: So is MS C++ compiler did some optimization or something to prevent this mechanism?


Solution

  • tl;dr

    Inside the C++ Object Model is a very old book, and most of its contents are implementation details of a particular compiler anyway. Don't worry about comparing your compiler to some ancient compiler.

    Full version

    An answer to the question linked to in a comment on this question addresses this quite well.

    The offset of something is how many units it is from the start. The first thing is at the start so its offset is zero.

    [...]

    Note that the ISO standard doesn't specify where the items are laid out in memory. Padding bytes to create correct alignment are certainly possible. In a hypothetical environment where ints were only two bytes but their required alignment was 256 bytes, they wouldn't be at 0, 2 and 4 but rather at 0, 256 and 512.


    And, if that book you're taking the excerpt from is really Inside the C++ Object Model, it's getting a little long in the tooth.

    The fact that it's from '96 and discusses the internals underneath C++ (waxing lyrical about how good it is to know where the vptr is, missing the whole point that that's working at the wrong abstraction level and you should never care) dates it quite a bit.

    [...]

    The author apparently led the cfront 2.1 and 3 teams and, while this books seems of historical interest, I don't think it's relevant to the modern C++ language (and implementation), at least those bits I've read.