如果你知道两条信息:
然后你逻辑上拥有引用该对象所需的一切:
#include <iostream>
using namespace std;
int main()
{
int x = 1, y = 2;
int* p = (&x) + 1;
if ((long)&y == (long)p)
cout << "p now contains &y\n";
if (*p == y)
cout << "it also dereference to y\n";
}
Run Code Online (Sandbox Code Playgroud)
但是,根据C++标准,这是不合法的.它适用于我尝试过的几个编译器,但它是未定义的行为.
问题是:为什么?
如果要将指针视为数字类型,首先需要使用std::uintptr_t
,而不是long
.这是第一个未定义的行为,但不是您正在谈论的行为.
它适用于我尝试过的几个编译器,但它是未定义的行为.
问题是:为什么?
好的,所以当我调用这个未定义的行为时,评论部分就消失了.它实际上是未指定的行为(也称为实现定义).
您正在尝试比较两个明显不相关的指针:
&x + 1
&y
指针&x+1
是一个一个接一个的指针.该标准允许您使用这样的指针,但只有在您使用它来与基于指针进行比较时才会定义行为x
.如果将其与其他任何内容进行比较,则不会指定该行为:[expr.eq§3.1]
编译器可以自由放置y
它选择的任何地方,包括寄存器.因此,无法保证&y
和&x+1
相关.
作为一个想要表明这是否实际上是未定义行为的人的练习,也许从这里开始:
[basic.stc.dynamic.safety§3.4]:
整数值是安全派生指针的整数表示,只有它的类型至少与std :: intptr_t一样大,并且它是以下之一:...
3.4加法或按位运算的结果,其中一个操作数是安全派生指针值P的整数表示,如果由reinterpret_cast转换的结果将等于可从reinterpret_cast(P)计算的安全派生指针.
注意:超出对象末尾的指针([expr.add])不被视为指向可能位于该地址的对象类型的无关对象
它会对优化造成严重破坏.
void f(int* x);
int g() {
int x = 1, y = 2;
f(&x);
return y;
}
Run Code Online (Sandbox Code Playgroud)
如果能有效方式"猜测"的地址y
来自x
的地址,然后调用f
可以修改y
,因此该return
语句必须重新加载的值y
从内存中.
现在考虑一个具有更多局部变量和更多其他函数调用的典型函数,在每次调用之前必须将每个变量的值保存到内存中(因为被调用的函数可以检查它们)并在每次调用后重新加载它们(因为被调用的函数可能已经修改过它们).
归档时间: |
|
查看次数: |
181 次 |
最近记录: |