Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does static_cast gives different memory locations for same object?

My code

class Parent { int a; };
class Child { int b; };
struct GrandChild : public Parent, public Child { int a, b, c; };

int main() {
    GrandChild GC;
    std::cout << "GrandChild's address is at : " <<&GC<<endl;
    std::cout << "Child's address is at : " <<static_cast<Child*>(&GC)<<endl;
    std::cout << "Parent's address is at : " <<static_cast<Parent*>(&GC)<<endl;

}

output:

GrandChild's address is at : 0077F6F8
Child's address is at : 0077F6FC
Parent's address is at : 0077F6F8

Why does after static_cast the memory locations have inconsistencies like above?

like image 978
InQusitive Avatar asked Aug 08 '15 08:08

InQusitive


3 Answers

GrandChild derives from both Parent and Child. As such, a GrandChild object in memory consists of both a Parent object and a Child object within its memory.

&GC by itself returns the memory address of the GrandChild object as a whole

static_cast<Parent*>(&GC) returns the starting address of the Parent portion inside the GrandChild object.

static_cast<Child*>(&GC) returns the starting address of the Child portion inside the GrandChild object.

In your case, Grandchild derives from Parent first, so the Parent portion is aligned at the beginning of the GrandChild's memory block. Then the Child portion follows the Parent portion. Here is an illustration to show that:

structure

like image 140
Remy Lebeau Avatar answered Oct 13 '22 00:10

Remy Lebeau


&GC is the address of the GrandChild object GC. static_cast<Child*>(&GC) is the address of the Child subobject of GC. And static_cast<Parent*>(&GC) is the address of the Parent subobject of GC.

In your particular implementation, it appears that a GrandChild object starts with a Parent subobject and then the Child subobject comes after, so the Parent subobject's address is the same as the complete GrandChild object's address, but the Child subobject's first byte is not the first byte of the complete GrandChild object, so its address is higher. You cannot rely on this behaviour being portable, however; different implementations may allocate base class and member subobjects in different orders, and do not even need to be consistent between different classes.

like image 40
Brian Bi Avatar answered Oct 12 '22 23:10

Brian Bi


In your example, it is predictable even if it is implementation defined (but implementers are allowed to choose straight solutions for simple cases :-) )

Here is the memory representation of your object (deduced from the addresses, not from the standard !):

Parent::a (int = 4 bytes)
Child::b (int = 4 bytes)
GrandChild::a
GrandChild::b
GrandChild::c

This is because of your declaration : GrandChild inherits first from Parent, next from Child. With that representation, it makes sense for Parent's address to be the same as GrandChild's one, and for Child'address to be 4 bigger.

Also note that GrandChild::a is not Parent::a...

like image 36
Serge Ballesta Avatar answered Oct 13 '22 01:10

Serge Ballesta