Beginner
Beginner

Reputation: 5467

How does the compiler distinguish nested objects if they have the same address?

In the following example (try out here)

#include <iostream>
using namespace std;

struct a {
    struct b {
        int b1;
    };
    b a1;
    int a2;
};
int main() {
    a test;
    test.a1.b1 = 5;
    test.a2 = 6;

    std::cout<<&test<<" "<<&(test.a1);
    // your code goes here
    return 0;
}

Both the struct and its nestd struct have the same memory location. This makes sense, since the first element to be stored in memory is part of the nested struct.

Proof: 0x7ffd895f86e0 0x7ffd895f86e0

My question is: how does the compiler know what types are stored at this location and is there any overhead from tracking such information at runtime to be expected?

Upvotes: 0

Views: 170

Answers (4)

The Quantum Physicist
The Quantum Physicist

Reputation: 26286

How about this:

struct a {
    int x;
    struct b {
        int b1;
    };
    b a1;
    int a2;
};

Do they have the same address? No. Not because they're different, but because "struct" has no binary meaning (before lashing this, keep reading). When your program is compiled, all that matters is the variables inside your structs. The programming language has this superficial thing called "struct" to make things easy for you. But it's not real, unless you do something that requires it to be handled as a one thing (such as copying it), and even then the binary code generated (for run-time) will only represent the elements that are to be copied as a whole, not the "struct", per se.

When you instantiate a there, this is how it looks like in memory:

int x - int b1 - int a2

It's blocks in memory with ints. It's not structs.

You can verify this using pointers. In your code:

*(int*)(&test) //is b1
*((int*)(&test)+1) //is a2

So you see there's only two ints in memory that matter.

PS: Notice that all this assumes that we're not dealing with polymorphism, which adds more memory blocks that represent the vtable. That's a story for another day.

Upvotes: 2

Pete Becker
Pete Becker

Reputation: 76315

Forget for a moment that you're dealing with structs. How does the compiler know that a particular memory location holds an int or a float? In one sense, it doesn't. But within a program, variables have a type and that type tells the compiler what operations are valid on that variable. It doesn't matter what the address of the object is; what matters is what type the program says it is. So:

int i = 3;
i = i + 1;

The compiler knows how to do that addition because the program said to treat the memory location named i as an int value.

float f = 4.0;
f = f + 1;

The compiler knows how to do that addition because the program said to treat the memory location named f as a float value.

In your example, test.a1.b1 has type int because the program said so. And test.a1 has type a::bbecause the program said so. Andtesthas typea` because the program said so.

Upvotes: 1

dodo951
dodo951

Reputation: 454

Actually it is you who explicitly tells the compiler what type is stored at a given location by writing expressions such as &test and &(test.a1).

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409196

Lets "draw" how the structure looks in memory (together with the "pointers" to it):

+----+----+
| a1 | a2 |
+----+----+
^    ^
|    |
|    &test.a2
|
&test
|
&test.a1

That should hopefully make it quite clear how two different structures can occupy the same memory.

It should be noted that this is only for structures with non-virtual functions. Virtual functions may cause other hidden members to be included in the objects.

Upvotes: 0

Related Questions