__unaligned指定符何时与指针一起使用?

时间:2018-06-21 18:34:07

标签: c++ c++11 templates visual-c++ memory-alignment

背景

我目前正在使用长度可变的数组,它们的长度存储在元素的前两个字节中。由于未填充数组,因此单个元素可能未对齐。确保仅第一个元素对齐,并且整个内容以double null结尾。这些数组供我需要访问且不能更改的API使用。

我正在写一个const_iterator,它使用对齐的指针,并且可以遍历未对齐的元素。这些数组的API为指向元素的指针指定了“ __unaligned”,因此我主要是试图确认或否认我对应用__unaligned说明符的理解。

问题

简而言之:在处理指向可能未对齐的数据的指针时,应何时使用__unaligned说明符?

让我们说我有

Foo *foo = pointerToFirstElement(); //aligned
auto next_ptr = reinterpret_cast<unsigned char *>(foo);
next_ptr += bytesToNextElement(foo);
//reinterpret_cast here to retrieve the next element

我是否需要检查新地址是否对齐,如果不对齐,请reinterpret_cast<Foo __unaligned *>(next_ptr)访问下一个元素?

进一步,我可以像这样__unaligned那样使用const作为模板参数推导的一部分吗?

template <class T, class = std::enable_if<std::is_pointer<T>::value>>
struct is_pointer_to_aligned_data : std::true_type {};

template <class T>
struct is_pointer_to_aligned_data<T __unaligned *> : std::false_type {};

2 个答案:

答案 0 :(得分:0)

在Visual C ++中,引入__unaligned关键字仅是为了支持Itanium,它需要对未对齐的读取进行特殊处理。这不适用于x86,x64或任何其他平台。

简而言之,根本不要使用它。

请参见MSDN

答案 1 :(得分:0)

  

简而言之:在处理指向可能未对齐的数据的指针时,应何时使用__unaligned指定符?

  • 简而言之,当您使用的平台需要它时,例​​如x86-64上的Windows API。这是对Itanium的遗留回溯,而与x86-32无关。其他一些处理器也存在未对齐数据的问题(例如MIPS)。

  • 具体地说,__unaligned说明符仅表示数据可能不在对齐的边界上。 It has no meaning outside of a pointer type.

  • 在32位x86平台上,Windows本身仅声明#define __unaligned

  

然后我是否需要检查新地址是否对齐,如果不对齐,则需要reinterpret_cast(next_ptr)来访问下一个元素吗?

  • 鉴于上述,不可以。添加__unaligned说明符对于访问带有参数的函数很有用,这些参数是指向未对齐数据的指针,例如ILFindLastID

  • 后续操作:在不需要时如何删除__unaligned指定符?使用const_cast或类似Windows:#define __unaligned,然后再添加标题。 使用预处理程序检查您是否在x86-64或其他安全的平台上。

最后,

  

此外,我是否可以像const这样,将__unaligned用作模板参数推导的一部分?

是的,但是像这样:

template< class T > struct is_aligned_helper : std::true_type {};
template< class T > struct is_aligned_helper<__unaligned T> : std::false_type {};
template< class T > struct is_aligned : is_aligned_helper<typename std::remove_cv_t<std::remove_pointer_t<T>>> {};

您需要先删除指针以检查指向数据的类型。然后删除所有const或volatile,以获取裸类型+ __unaligned(如果存在)。