【问题标题】:C/C++ pointer tricks (saving pointer to int, and translating back)C/C++ 指针技巧(保存指向 int 的指针并翻译回来)
【发布时间】:2011-11-20 04:20:00
【问题描述】:

正如标题所说,我目前正在用 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

【问题讨论】:

  • “在 C++ 中使用指针的一些小技巧”几乎从来都不是一个好主意。你想达到什么目的?
  • 在许多 64 位架构上 sizeof(int) != sizeof(void*),检查一下。
  • 是否涉及子类化?
  • @@Ben uintptr_t 不确保它的大小相同吗?
  • 请不要这样做。为自己节省数小时的痛苦和重新编码。请不要这样做。

标签: c++ pointers casting void-pointers


【解决方案1】:

这一行:

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

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

你可以这样做:

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

(即创建对旧的引用)。

但一般来说,像这样搞乱指针是麻烦大于它的价值。

【讨论】:

  • 感谢您的解决方案,但我很乐意告知;我不会使用它。 - 制作了一个更漂亮、更安全但速度较慢的解决方案。
【解决方案2】:

对于 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 位保证足够大的假设。
  • 不是可移植的吗?
【解决方案3】:

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

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

应该是:

uintptr_t texture_pointer = (uintptr_t)&texture;

(假设您出于某种原因想要使用 C 风格的转换而不是正确的 C++ 转换)。

【讨论】:

    【解决方案4】:

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

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

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

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

    【讨论】:

      【解决方案5】:

      如果我正确地计算了“*”这一行

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

      创建纹理指针指向的任何内容的副本。

      所以,texture 和 *texture_pointer 是不同的存储位置,这就是 &texture 和 texture_pointer 具有不同值的原因。

      【讨论】:

        【解决方案6】:
        Texture texture = *(Texture*)((void*) texture_pointer);
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多