__unaligned 说明符何时与指针一起使用?
When is the __unaligned specifier used with pointers?
背景
我目前正在使用可变长度数组,其长度存储在元素的前两个字节中。由于数组未填充,因此单个元素可能未对齐。只有第一个元素保证对齐,整个事情都是双空终止的。这些数组由我需要访问但无法更改的 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)
访问下一个元素?
此外,我可以像这样以类似于 const
的方式使用 __unaligned
作为模板参数推导的一部分吗?
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 {};
对于 Visual C++,引入 __unaligned
关键字只是为了支持 Intel Itanium (_M_IA64
),它需要对未对齐的读取进行特殊处理。
Windows Server 2008 R2 和 Windows XP x64 Edition 是 [=30 的最新版本=] 支持 Itanium.
这不适用于 Windows x86、x64、ARM 或 ARM64。
简而言之,不要在代码中使用它。
Simply: when should the __unaligned specifier be used when dealing with pointers to potentially unaligned data?
简而言之,当您使用的平台需要它时,例如x86-64 上的 Windows API。这是对 Itanium 的传统回归,而不是 x86-32 上的问题。其他一些处理器也有未对齐数据的问题(例如 MIPS)。
具体来说,__unaligned
说明符仅表示数据可能不在对齐边界上。 It has no meaning outside of a pointer type.
在 32 位 x86 平台上,Windows 本身只是声明 #define __unaligned
。
Do I then need to check if the new address is aligned, and if not, reinterpret_cast(next_ptr) to access the next element?
综上所述,不是。添加 __unaligned
说明符对于访问采用指向未对齐数据指针的参数的函数很有用,例如 ILFindLastID
.
跟进: 如何删除不需要的 __unaligned 说明符?在包含 header 之前使用 const_cast
或像 Windows: #define __unaligned
这样的操作。 使用预处理器检查您使用的是 x86-64 还是其他安全平台。
最后,
Further, can I use __unaligned as part of template argument deduction in a manner similar to const, like so?
是的,但是像这样:
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
(如果存在)。
背景
我目前正在使用可变长度数组,其长度存储在元素的前两个字节中。由于数组未填充,因此单个元素可能未对齐。只有第一个元素保证对齐,整个事情都是双空终止的。这些数组由我需要访问但无法更改的 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)
访问下一个元素?
此外,我可以像这样以类似于 const
的方式使用 __unaligned
作为模板参数推导的一部分吗?
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 {};
对于 Visual C++,引入 __unaligned
关键字只是为了支持 Intel Itanium (_M_IA64
),它需要对未对齐的读取进行特殊处理。
Windows Server 2008 R2 和 Windows XP x64 Edition 是 [=30 的最新版本=] 支持 Itanium.
这不适用于 Windows x86、x64、ARM 或 ARM64。
简而言之,不要在代码中使用它。
Simply: when should the __unaligned specifier be used when dealing with pointers to potentially unaligned data?
简而言之,当您使用的平台需要它时,例如x86-64 上的 Windows API。这是对 Itanium 的传统回归,而不是 x86-32 上的问题。其他一些处理器也有未对齐数据的问题(例如 MIPS)。
具体来说,
__unaligned
说明符仅表示数据可能不在对齐边界上。 It has no meaning outside of a pointer type.在 32 位 x86 平台上,Windows 本身只是声明
#define __unaligned
。
Do I then need to check if the new address is aligned, and if not, reinterpret_cast(next_ptr) to access the next element?
综上所述,不是。添加
__unaligned
说明符对于访问采用指向未对齐数据指针的参数的函数很有用,例如ILFindLastID
.跟进: 如何删除不需要的 __unaligned 说明符?在包含 header 之前使用
const_cast
或像 Windows:#define __unaligned
这样的操作。 使用预处理器检查您使用的是 x86-64 还是其他安全平台。
最后,
Further, can I use __unaligned as part of template argument deduction in a manner similar to const, like so?
是的,但是像这样:
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
(如果存在)。