struct fraction {
int num;
int denum;
} pi;
pi.num=22;
pi.denum=7;
((fraction*)&(pi.denum))->num=12;
cout << endl;
cout << pi.denum <<endl;
cout << pi.num <<endl;
I can understand the memory diagram till this point What I have confusion is is the following code
((fraction*)&pi.denum)->denum=33;
Is there a legal way to get that 33 printed out ?? ANY command to get the value stored which is not in the view of an object?
First if you want to print out the 33 than you need to use following instruction:
Now understand the C memory access mechanisum the struct fraction have two int member. The base address of struct point to first element address.
&pi.denum give the second element address now you cast it to the struct pointer so it treat the denum address as num address logically but physically it denim address.
So if you want to change the denim value you have to use the first element address which point to denim address.
A
struct fraction
will be layed out in memory as two consecutiveints
. Your code looks at the expression&pi.denum
, which is the address of the second integer:But you cast
&pi.denum
to afraction *
and try to access((fraction*)&(pi.denum))->num
. Sincenum
is the first member ofstruct fraction
, the C standard guarantees that its address is the same as the struct itself. SoIt is a valid memory location - but only by luck. If you tried to access
((fraction*)&(pi.denum))->denom
, you'd get undefined behavior - possibly corrupting memory or causing a segmentation fault.Bottom line,
((fraction*)&(pi.denum))->num = 12
is nonsense code. It could never do anything useful.In the code posted in your question, you have told the compiler to act as if the address of
pi.denum
is actually the address of afraction struct
.It is not, and therefore you are on your own in getting the memory addressing right. C (or C++) will lay out your struct in memory in the order you specify, subject only to padding for alignment.
So, on a machine with 32-bit ints and typical 32-bit alignment for 32-bit ints, your line
((fraction*)&(pi.denum))->num=12;
will setpi.denum
to 12, notpi.num
. The->num
is an offset from a pointer (the offset is zero) and your pointer is topi.denum
, so it ispi.denum
that gets set.This will not crash, because you have simply used a peculiar expression to address memory that is properly allocated on your stack.
The following code
((fraction*)&pi.denum)->denum=33;
will write to memory outside of the allocation ofpi
. Whether this crashes or simply overwrites another variable depends on what else you have allocated on the stack and perhaps on your compiler and compiler settings.If you actually want to scribble on the memory that follows your struct and then read it back, the same addressing expression will do it for you, e.g.
Maybe a simple image will help:
A
is the base address wherepi
is stored in memory.num
is stored at addressA+0
anddenum
is stored at addressA+4
(if anint
is 32 bits, i.e. 4 bytes).The
((fraction*)&(pi.denum))
part of the statement will make the layout look something like this:As you can see there is an overlap in memory. This means that the statement
((fraction*)&(pi.denum))->num=12;
will actually setpi.num
to 12.Also as you can see, if you try to set
((fraction*)&(pi.denum))->denum
to a value, you are now writing outside of the memory allocated to thepi
structure, and may overwrite other variables or other things.Provided that this code is basically wrong, maybe you are searching for this:
That line probably will set pi.denum to 12, but it's undefined behavior. The member "num" is (in most cases) in the beginning of the struct, so
something.num
is like(int)something
(of course, thissomething
must be a fraction), but you should not assume that it will work on every machine.