Look at this simple code:
struct Point {
int x;
int y;
};
void something(int *);
int main() {
Point p{1, 2};
something(&p.x);
return p.y;
}
I expect, that main
's return value can be optimized to return 2;
, as something
doesn't have access to p.y
, it only gets a pointer to p.x
.
But, none of the major compilers optimize the return value of main
to 2
. Godbolt.
Is there something in the standard, which allows something
to modify p.y
, if we only give access to p.x
? If yes, does this depend on whether Point
has standard layout?
What if I use something(&p.y);
, and return p.x;
instead?
This is perfectly well-defined:
void something(int *x) {
reinterpret_cast<Point*>(x)->y = 42;
}
The Point
object (p
) and its x
member are pointer-interconvertible, from [basic.compound]:
Two objects a and b are pointer-interconvertible if:
- [...]
- one is a standard-layout class object and the other is the first non-static data member of that object, or, if the object has no non-static data members, any base class subobject of that object ([class.mem]), or:
- [...]
If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a
reinterpret_cast
.
That reinterpret_cast<Point*>(x)
is valid and does end up with a pointer that points to p
. Hence, modifying it directly is fine. As you can see, the standard-layout part and the first non-static data member part are significant.
Although it's not like the compilers in question optimize out the extra load if you pass a pointer to p.y
in and return p.x
instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With