是否有可能通过指向另一个未释放子对象的指针来获得一个子对象的指针?

gez*_*eza 51 c++ pointers offsetof language-lawyer c++17

看下面这个简单的代码:

struct Point {
    int x;
    int y;
};

void something(int *);

int main() {
    Point p{1, 2};

    something(&p.x);

    return p.y;
}
Run Code Online (Sandbox Code Playgroud)

我希望main可以将返回值优化为return 2;,因为something它无法访问p.y,只能返回的指针p.x

但是,没有一个主要的编译器会优化mainto 的返回值2上帝保佑

如果仅允许访问,标准中是否存在可以something修改的内容?如果是,这是否取决于标准布局?p.yp.xPoint

如果我使用something(&p.y);,该return p.x;怎么办?

Bar*_*rry 51

这是定义明确的:

void something(int *x) {
    reinterpret_cast<Point*>(x)->y = 42;
}
Run Code Online (Sandbox Code Playgroud)

[basic.compound]起,Point对象(p)及其x成员是指针可互换的

如果满足以下条件,则两个对象ab指针可互换的

  • [...]
  • 一个是标准布局类对象,另一个是该对象的第一个非静态数据成员,或者,如果该对象没有非静态数据成员,则该对象的任何基类子对象([class.mem]) , 要么:
  • [...]

如果两个对象是指针可互换的,则它们具有相同的地址,并且可以通过指向另一个指向另一个指针reinterpret_­cast

reinterpret_cast<Point*>(x)是有效的,并且确实以指向的指针结尾p。因此,直接修改它很好。如您所见,标准布局部分和第一个非静态数据成员部分很重要。


尽管这不像所涉及的编译器优化的额外负担,如果您将指针传递给p.yin并返回p.x

  • 我在这里想念什么吗?强制转换将指向px的指针更改为指向Point的指针,但是仍然指向相同的存储位置吗?那将意味着这只起作用,因为“ x”是第一个成员,因此与“父”对象“点p”存在相同的存储位置。因此,如果我们将`&p.y`传递给函数,则会得到不同的行为(未定义?) (3认同)
  • 这不违反严格混叠规则吗?还是仅C规则? (2认同)
  • @ sturcotte06并不是因为*如果两个对象是指针可互换的,则它们具有相同的地址,并且可以通过reinterpret_cast从指向另一个的指针获得指向一个的指针。 (2认同)