查询特定变量的对齐方式

Query the alignment of a specific variable

本文关键字:对齐 方式 变量 查询      更新时间:2023-10-16

C++11引入了alignas说明符来指定变量的对齐方式,并引入了alignof运算符来查询类型的默认对齐方式。然而,我看不出有任何方法可以使特定变量对齐。让我们举以下琐碎的例子:

alignas(16) float* array;

以下是我们可以做的:

  • alignof(float*)返回8,这显然不是我们想要的
  • alignof(array)返回16,这正是我们想要的,但这是一个编译器扩展;标准中指定的alignof不能用于特定变量
  • alignof(decltype(array))返回8,这是意料之中的,但不是我们想要的
  • std::alignment_of是在alignof的基础上实现的,所以它没有多大帮助

我想要一种机制来确认特定变量array在16字节边界上对齐。标准中是否有执行此类查询的内容?

您可以尝试使用以下内容:

bool is_aligned(const volatile void *p, std::size_t n)
{
  return reinterpret_cast<std::uintptr_t>(p) % n == 0;
}
assert(is_aligned(array, 16));

以上假设了平坦的地址空间,并且CCD_ 10上的算术等同于CCD_ 11上的算术。

虽然这些条件适用于大多数现代平台,但这两种条件都不是标准所要求的。

当将void *强制转换为uintptr_t时,实现完全可以执行任何转换,只要从uintptr_t强制转换回void *时可以反转转换即可(请参阅什么是uintptr_t数据类型)。

N4201中的进一步细节(除其他外,它提出了is_aligned()操作)。


编辑

这里需要volatile吗?

它允许类似以下内容:

alignas(16) volatile float a;
assert(is_aligned(&a, 16));

如果没有volatile,您会得到错误

第一个参数没有从"volatile float*"到"const void*"的已知转换

进一步参考:

  • 为什么以及何时被强制转换为char volatile&需要吗
  • 为什么一个指向易失性指针的指针,比如";volatile int*p";,有用吗

这目前由EWG 98处理。我提交了一篇关于的论文

alignas说明符适用于对象,影响它们的对齐要求,但不影响它们的类型。因此,目前无法确定对象的实际对齐要求。本文提出允许alignof应用于对象和引用。

在这个时间点上,你能做的最好的事情就是定义一个单独的变量来保持变量的对齐。

你可以试试这个:

template<size_t size, typename T>
constexpr bool IsAlignedAs(const T& v)
{
    return (reinterpret_cast<const size_t>(&v) % size) == 0;
}
std::cout << IsAlignedAs<16>(array) << std::endl;
std::cout << IsAlignedAs<32>(array) << std::endl;