【问题标题】:Restoring bitfield truncated addresses恢复位域截断地址
【发布时间】:2021-03-07 05:02:44
【问题描述】:

我想通过将指针地址截断 1 个字节来节省一些空间。我的指针保证是 16 字节内存对齐的。因此,我可以保证这 4 个低位可以被截断。

typedef struct node_t {
   uintptr_t prev : 29;
   uintptr_t next : 29;
} node;

我正在努力恢复那些最底层的字节。向左位移 4 位以尝试恢复最底部位中的零只会擦除最前面字节中的数据。

node->next = ((uintptr_t) ptr_addrs >> 4); // successfully stores truncated pointer ex: 0x1024ff010
printf("%p\n", node->next); // prints '0x1024ff01'

如何将位域转换回其原始值(基本上是在该位域上附加一个零)?

【问题讨论】:

  • 你有没有检查过这是否真的对sizeof(node)有任何影响?
  • 是的;在我的系统上,如果我要使用完整字段,我会得到 sizeof(node) = 16,而使用 bitfields 有 sizeof(node) = 8
  • 所以你正在编译 64 位?
  • 是的;在 Linux 64 位机器上;使用 gcc 编译
  • @RetiredNinja:老实说,我已经遇到了从哪里开始的问题,这一切都错了。这就是为什么我试图将他指向研究的主题。

标签: c pointers bit-fields


【解决方案1】:

首先,如果指针是 32 位,则删除 4 位会留下 28 位,而不是 29 位。因此,声明 29 位的位域似乎是错误的。没有平台使用 33 位作为指针。 29 位当然足以存储 28 位,但它太大而无法节省任何空间——结构的总空间要求至少为 58 位,这需要 8 个 8 位字节,因为 7 个字节只能容纳 56位。

其次,为结构使用“完整字段”需要 16 个字节,这表明 uintptr_t 是 8 个字节,因此平台的指针是 8 个字节,64 位。从中删除 4 位会留下 60 位,而不是 28 或 29。

要回答您的问题“如何将位域转换回其原始值”,只需将左移四位并转换回原始指针类型即可。

(有时使用 64 位作为指针的系统不会使用所有这些位;实际地址空间可能是 44 位或其他数字,在这种情况下,您可以通过仅存储使用的位来节省空间。但是,这根据当今的经济学,某种指针压缩非常耗时,并且只能节省少量空间。除非您的主内存溢出了由大部分指针组成的结构,否则不太值得。每个指针节省的空间量是否会成倍增加通过指针数量将内存使用量减少到性能下降的阈值以下?)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-13
    • 1970-01-01
    • 2014-05-15
    • 1970-01-01
    • 2014-06-21
    • 2017-06-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多