C/C++指针技巧(将指针保存到int,并转换回)

C/C++ pointer tricks (saving pointer to int, and translating back)

本文关键字:指针 int 转换 C++ 保存      更新时间:2023-10-16

正如标题所说,我目前正在用C++中的指针进行一些小技巧,但有些东西不起作用:

uintptr_t texture_pointer = (int)((void*) &texture);

其中纹理是一个类;这似乎很好,因为我得到了一个指针值,并且我已经保证我在我的另一个函数中得到了相同的值,这个函数应该会把对象拿回来;这是失败的代码:

std::cout << "C++ BEFORE: " << texture_pointer << std::endl;
Texture texture = *(Texture*)((void*) texture_pointer);
std::cout << "C++ AFTER: " << (uintptr_t)((void*) &texture) << std::endl;

我的输出除外;是同一个数字,但我得到了两个不同的数字,因此我认为一定有错误,但我似乎找不到。

示例输出:

C++ BEFORE: 2685236
C++ AFTER: 2684960

此行:

Texture texture = *(Texture*)((void*) texture_pointer);

创建一个Texture对象作为原始对象的副本。显然,这与旧的地址不同。

你可以这样做:

Texture &texture = *(Texture*)((void*) texture_pointer);

(即创建一个对旧引用的引用(。

但总的来说,像这样的指针太麻烦了。

对于到void指针和从void指针进行强制转换,请使用static_cast。对于向整数转换和从整数转换,请使用reinterpret_cast:

SomeType* p;
// Make sure the type can hold a pointer.
std::uint64_t i = reinterpret_cast<std::uint64_t>(p);
...
SomeType* q = reinterpret_cast<SomeType*>(i); // Guaranteed to yield p back

除了其他答案中已经指出的错误外,这一行是不正确的,很可能在64位系统(LP64(上失败:

uintptr_t texture_pointer = (int)((void*) &texture);

应该是:

uintptr_t texture_pointer = (uintptr_t)&texture;

(假设出于某种原因,您希望使用C样式的强制转换,而不是正确的C++强制转换(。

最初,您获取在堆栈上而不是堆上分配的对象的地址。线路:

Texture texture = *(Texture*)((void*) texture_pointer);

然后将该对象复制到堆栈上分配的另一个对象中。然后你取第二个地址的地址。

当您处理两个不同的对象时,您有两个不同地址。

如果我正确计算了'*,则此行

Texture texture = *(Texture*)((void*) texture_pointer);

创建每个texture_pointer指向的内容的副本。

因此,texture和*texture_pointer是不同的存储位置,这就是为什么&texture和texture_pointer具有不同的值。

Texture texture = *(Texture*)((void*) texture_pointer);

这一行创建了一个新对象,并将texture_pointer指向的对象分配给它。这与创建指针并使其指向对象不同。当您将一个对象分配给另一个对象时,基本上就是将旧对象的内容复制到新对象中。因此,这两个打印的地址是不同的是有道理的——它们是两个不同对象的地址。