Address of struct and address of first member variable

The address of a struct is the same as the address of its first member variable.

1
2
3
4
5
6
7
8
9
10
11
  struct myStruct{
    int number;
    char ch;
};

int main()
{
    myStruct mystruct = {8,'a'};
    
    cout << &mystruct << endl;
    cout << &(mystruct.number) << endl;

This prints out the same address. So far so good. Building on this fact I want to access the first member variable using the address of the struct.
Something like this:
 
cout << *(&mystruct);

I know this is pointless but it is for the sake of learning. Adding the above line makes the code not compile. I tried casting the pointer to an int pointer like so:
 
cout << (int *)*(&mystruct);

But I still get an error (error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream}’ and ‘myStruct’))

Given that both the struct and the first member have the same address, how do we access the member from the struct's address, like I am trying to do above?

And how does the compiler differentiate between doing something with the struct vs doing someting with the first member, if they both share the same address?
Do you mean this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;

struct myStruct {
	int number;
	char ch;
};

int main()
{
	myStruct mystruct = {8,'a'};

	cout << &mystruct << endl;
	cout << &(mystruct.number) << endl;

	cout << *(int*)&mystruct << endl;
}



000000000019FA80
000000000019FA80
8


But only do things like this for learning purposes!

NB. Read code such as L16 from right to left. Get the address of the struct, cast as a pointer to int (first member), then de-reference this int pointer.
Last edited on
Start with
cout << mystruct.number;

Then do
cout << *(&mystruct.number);
It's like the * and the & cancel out, getting you back to where you started.



And how does the compiler differentiate between doing something with the struct vs doing someting with the first member, if they both share the same address?

Because they have different types.
&mystruct is a pointer to the whole structure.
&mystruct.number is a pointer to an integer.


the 'struct' is sort of a 'false entity'. Down in the CPU, there is no such thing as a struct.

maybe this will help...

int i{};
uint8_t bytearray[1000];

int * ip = (int*)bytearray;
i += sizeof(int);
double *dp = (double*)(&bytearray[i]);
i+= sizeof(double);
string *sp = (string*)(&bytearray[i]);
...
this is a 'struct', sort of.
the fields are ip, dp, and sp.

this is (very, very roughly) what the compiler is doing when it turns a 'struct' into machine language, though bytearray would just be ram direct memory offsets.

so you can move the 'struct' around by moving 'bytearray' around as a 'group of bytes', but that is just organization, a 'way to look at it'. there is no 'struct' thing in reality, its just a way to say "this many bytes in a block" when talking at the struct level or "this offset from the starting address" when talking about its fields. That is why the struct and first field share an address: its just a different way of looking at the same block of bytes.

at the c++ level, a struct IS a thing, and a tool you can do a lot with. But that is just a syntax that hides what needs to be done to express it. You do not really care about the memory layout details when using a struct, you just use it and let the compiler do the ugly stuff for you.
Last edited on
> Given that both the struct and the first member have the same address

This is not guaranteed, except for standard layout types
https://en.cppreference.com/w/cpp/named_req/StandardLayoutType

The object representation of standard layout types are as specified by the C language,
in particular:
A pointer to an object of standard-layout class type can be reinterpret_cast to pointer to its first non-static non-bitfield data member (if it has non-static data members) or otherwise any of its base class subobjects (if it has any) (since C++11), and vice versa. In other words, padding is not allowed before the first data member of a standard-layout type. Note that strict aliasing rules still apply to the result of such cast.
https://en.cppreference.com/w/cpp/language/data_members#Standard_layout
Topic archived. No new replies allowed.