Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to get a pointer to one subobject via a pointer to a different, unreleated subobject?

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?

like image 935
geza Avatar asked Sep 17 '19 17:09

geza


1 Answers

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.

like image 186
Barry Avatar answered Oct 17 '22 09:10

Barry