I'm reading the book Inside the C++ Object Model. In the book there's an example like:
struct Base1
{
int v1;
};
struct Base2
{
int v2;
};
class Derived : public Base1, public Base2 {};
printf("&Derived::v1 = %p\n", &Derived::v1); // Print 0 in VS2008/VS2012
printf("&Derived::v2 = %p\n", &Derived::v2); // Print 0 in VS2008/VS2012
In the previous code, the print of address Derived::v1 & Derived::v2 will both be 0. However, if print the same address via a variable:
int Derived::*p;
p = &Derived::v1;
printf("p = %p (&Derived::v1)\n", p); // Print 0 in VS2008/VS2012 as before
p = &Derived::v2;
printf("p = %p (&Derived::v2)\n", p); // Print 4 in VS2008/VS2012
By examining the size of &Derived::v1 and p, I get 4 in both.
// Both are 4
printf("Size of (&Derived::v1) is %d\n", sizeof(&Derived::v1));
printf("Size of p is %d\n", sizeof(p));
The address of Derived::v1 will be 0, but the address of Derived::v2 will be 4. I don't understand why &Derived::v2 became 4 when assign it to a variable.
Examine the assembly code, when directly query the address of Derived::v2, it is translated to a 0; but when assign it to a variable, it gets translated to a 4.
I tested it on both VS2008 & VS2012, the result is the same. So I think there's must be some reason to make Microsoft choose such design.
And, if you do like this:
d1.*(&Derived::v2) = 1;
Apparently &Derived::v2 is not 0. Why does the compiler distinguish this two cases?
Can anyone please tell the thing happens behind? Thank you!
--Edit--
For those think the &Derived::v1 doesn't get a valid address. Haven't you ever did this?
Derived d1, d2;
d1.*p = 1;
d2.*p = 1;