The C++ standard (quoting from draft n3242) says the following about subobjects [intro.object]:
Unless an object is a bit-field or a base class subobject of zero size, the address of that object is the address of the first byte it occupies. Two distinct objects that are neither bit-fields nor base class subobjects of zero size shall have distinct addresses.
Now, given the following snippet:
struct empty { };
struct member: empty { };
struct derived: empty { member m; };
int main(void)
{
printf("%d", sizeof(derived));
return 0;
}
gcc I believe prints out 2
, and Visual C++ 2010 prints out 1
. I suspect gcc is taking the standard to mean you can't alias the storage of types if they represent different objects. And I bet MSVC is taking the standard to mean if one subobject is zero sized, you can do whatever you want.
Is this unspecified behavior?
Expanding on my earlier comment:
An object is identified by its address. If you compare the addresses (like pointers) of two objects of the same type and they compare equal, the pointers are considerd to point to the same object.
Objects of different types cannot be compared directly this way, so they are allowed to have the same address. One example is a struct and its first member. They cannot be of the same type. Neither can a base class and a derived class, so they could possibly have the same address if the base class is empty.
However, a base class and the first member of the derived class can be of the same type. This is not a problem unless the base class is also empty and the compiler tries the empty base class optimization. In that case we could have pointers to two different objects of the same type compare equal, and therefore believe that they were the same object.
So, if the members have different types (empty and char) they can have the same address. If they are of the same type they cannot, because that would break tests for object identity like
if (this != &that)
, sometimes used to test for things like self assignment.By the way, Microsoft agrees that this is a bug in their compiler but have other, more urgent, things to fix first.