3

我想使用一个长整数,当设置 MSB 时它将被解释为一个数字,否则它将被解释为一个指针。那么这是否可行,或者我会在 C 或 C++ 中遇到问题吗?

这是在 64 位系统上。

为清楚起见和更好的描述进行了编辑。

4

9 回答 9

14

在 x86-64 上,您将有一个地址超过 47 位的指针设置了第 63 位,因为“架构支持的最大位数”(当前为 48)以上的所有位都必须具有相同的值作为值本身的最高有效位。(也就是说,任何高于 0007 FFFF FFFF FFFF 的地址都将是 FFF8 0000 0000 0000 - 其间的所有内容都作为指针“无效”)

这很可能只是内核使用的地址,但我不确定它是否保证。

但是,我会尽量避免使用这样的技巧——它很可能会在某个时候卷土重来并困扰你。

于 2013-05-20T20:59:27.260 回答
6

人们以前尝试过这样的伎俩

从长远来看,它永远不会奏效。

干脆不要这样做。

编辑:更好的链接- 请参阅对“bit31”的引用,以前从未按设置返回。一旦可以设置它(超过 2 gigs 的 RAM,喘不过气来!)它会破坏顽皮的程序,因此一旦这么多内存成为常态,因为人们使用了像这样的诡计(除其他外),程序需要选择这个选项。现在我可爱的、简短的、中肯的答案变得太长了:-)

于 2013-05-20T20:57:40.063 回答
4

那么这是否可行,或者我会在 C 或 C++ 中遇到问题吗?

你有64位吗?您希望您的代码可移植到 32 位系统吗? long不一定有 64 位。大端与小端?(你知道你的系统是什么吗?)

另外,无可救药的混乱。请只使用一个额外的变量来存储此信息,否则您将遇到许多围绕此的错误。

于 2013-05-20T20:55:40.867 回答
3

这取决于架构。例如,x86_64架构当前使用 48 位寻址。这意味着您可以根据自己的需要使用 16 位(有时称为“指针打包”的技巧)。然而,即使 x86_64 架构定义也允许在未来的实现中将此限制提高到完整的 64 位。如果发生这种情况,您可能会遇到需要更改大量代码的情况。因此,如果您真的必须这样做,请确保您的指针包装保存在一个将来易于更改的地方。对于其他架构,您必须自己检查。

于 2013-05-20T20:58:56.590 回答
1

除非你真的需要空间,或者你保留了很多这些东西,否则我只会使用一个普通的联合,并添加一个标签字段。如果你打算走那条路,请确保你的记忆符合你的需求。

于 2013-05-20T21:07:35.490 回答
1

看看boost::lockfree::detail::tagged_ptr来自boost.lockfree

这是在最新的 1_53 boost 中引入的类。它将指针和额外的 16 位存储在 64 位变量中。

于 2013-05-20T21:03:48.163 回答
0

不要做这样的把戏。如果您需要将整数与某个容器内的指针区分开来,请考虑使用单独bit set的来指示此类标志。在 C++std::bitset中可能已经足够好了。

原因:

  • 实际上没有人保证指针是long unsignedor long long unsigned。如果您需要存储它们,请始终应用sizeof()void *键入(如果您需要删除有关指向对象的信息)。
  • 即使在一个系统上,地址也高度依赖于架构。
  • 内核模块可能会严重改变进程的映射逻辑,所以你永远不知道你需要什么地址。
于 2013-05-20T21:44:00.197 回答
0

如果有问题的“64 位系统”是 x86_64,那么是的,它可以工作。

于 2013-06-03T16:13:53.470 回答
0

请记住,返回给您的程序的虚拟地址可能必然与内存中的实际物理地址对齐。事实上,除非您直接操作非常特殊的内存(例如某些形式的图形内存),否则绝对是这种情况。

在这种情况下,它是 MMU 的最大值,它定义了程序看到的指针的值。在这种情况下,对于 x64,我很确定它(当前)是 48 位,但是正如 Mats 在上面指定的那样,一旦你在 48 中设置了最高位,你也会得到 63 位。

因此,接受他的答案和我的答案 - 即使使用少量 RAM,也完全有可能获得第 47 位设置的指针,并且一旦你得到第 63 位设置。

于 2013-05-20T21:17:49.100 回答