【问题标题】:Aligning an address forward向前对齐地址
【发布时间】:2018-12-24 14:25:19
【问题描述】:

我正在阅读 gameDev https://www.gamedev.net/articles/programming/general-and-gameplay-programming/c-custom-memory-allocation-r3010/ 上的这篇自定义内存管理器文章 他们有一种方法可以向前对齐地址。但是,我就是不明白

inline void* alignForward(void* address, u8 alignment) 
{
      return (void*)((reinterpret_cast<u8*>(address) + static_cast<u8>(alignment-1)) & static_cast<u8>(~(alignment-1)));
}

作者是这样解释的。 “为了 n 字节对齐内存地址 x,我们需要从 x 中屏蔽 log2(n) 最低有效位。简单地屏蔽位将返回 x 之前的第一个 n 字节对齐地址,因此为了找到之后的第一个x 我们只需要将alignment-1 添加到x 并屏蔽该地址。”

我了解您为什么需要屏蔽 log2(n) 最低有效位。但是,该方法不起作用。我已经用几个数字手动尝试过。例如,如果地址为 17(十进制)且对齐方式为 6(十进制),则该方法应返回 18,但事实并非如此。也许是因为我不明白为什么作者使用 u8(这是我在互联网上阅读的无符号字符)进行对齐。使用int进行对齐不是更直观吗?

【问题讨论】:

  • 此外,&amp; 的左操作数是u8*u8*+u8 的结果),其右操作数是u8。如果我是 C++ 编译器,我会拒绝该代码。
  • 将数字与 2 的幂对齐的公式比将数字与任意数字对齐的通用公式要高效得多。鉴于内存对齐始终是 2 的幂,那么使用优化版本是有意义的。任意对齐基本上需要加法、乘法和除法,而除法通常是一个相对较慢的操作。

标签: c++


【解决方案1】:

在 C 和 C++ 中,对齐总是 2 的幂。有很多位旋转技术只有在对齐是 2 的幂时才有效。

该函数所做的基本上是添加alignment - 1,然后向下舍入到下一个对齐倍数。所有对齐的倍数都将其最后的log2(alignment) 位设为 0(因为它是 2 的某个幂),并且掩码只是将最后几位设置为 0。

【讨论】:

  • 嗨,他们为什么要使用 u8 呢?有什么原因吗?此外,对于我上面的示例,您可以在 22(二进制 10110)和 ~5(二进制 10)之间执行 & 运算符,这将得到 10(十进制 2),但我们想要 18。获得 18 的唯一方法是我们保持前 3 位不变。抱歉,解释太长了,我对此很陌生,很困惑。
  • @HarryKane 因为alignment 看起来像1000...(所以你的例子不起作用,因为6 不是2 的幂)在二进制中,alignment - 1 看起来像1111...~(alignment - 1) 看起来像 ..111100000... (翻转位),如果你 &amp; 它,它基本上会将最右边的位归零。 u8 在技术上是错误的。它应该是std::size_t,就像alignof(...) 返回的一样。但最大值通常为 8 或 16,对于 long double,可以保存在 u8 中(u8 中最大值为 255)
猜你喜欢
  • 2012-04-18
  • 2018-05-02
  • 2017-07-20
  • 2016-05-16
  • 1970-01-01
  • 1970-01-01
  • 2011-02-02
  • 2013-03-08
  • 1970-01-01
相关资源
最近更新 更多