C++ 具有单字节对齐方式的结构是否可以安全地使用字节数组
是C++ 具有单字节对齐方式的结构是否可以安全地使用字节数组,c++,memory,c++14,C++,Memory,C++14,是struct alignas(1)字节{}可用于分配任意数量的字节和指针算法的安全性?我更喜欢使用这种字节类型而不是字符数组,因为字节需要转换成另一种类型才能使用 快速使用示例: #include <cstring> #include <iostream> struct alignas(1) byte {}; class Any { byte* mData; public: template<class T> explicit A
struct alignas(1)字节{}代码>可用于分配任意数量的字节和指针算法的安全性?我更喜欢使用这种字节类型而不是字符数组,因为字节需要转换成另一种类型才能使用
快速使用示例:
#include <cstring>
#include <iostream>
struct alignas(1) byte {};
class Any
{
byte* mData;
public:
template<class T>
explicit Any(T pValue) : mData(new byte[sizeof(T)]) {
std::memcpy(mData, &pValue, sizeof(T));
}
~Any() {
delete[] mData;
}
template<class T>
auto get() -> T& {
return *(T*)(mData);
}
};
int main()
{
int i = 5;
Any a(i);
std::cout << a.get<int>() << std::endl;
}
#包括
#包括
结构alignas(1)字节{};
任何类别
{
字节*mData;
公众:
模板
显式Any(tpvalue):mData(新字节[sizeof(T)]){
std::memcpy(mData和pValue,sizeof(T));
}
~Any(){
删除[]mData;
}
模板
自动获取()->T&{
返回*(T*)(mData);
}
};
int main()
{
int i=5;
任何a(i);
STD::CUT不能分配4个字节,然后考虑第一个地址是4字节对象的地址,因为可能有对齐要求。
例如,在一些硬件平台中,访问地址不是4的倍数的4字节整数是一个segfault,而不仅仅是一个性能问题。您使用的是一个C风格的强制转换:return*(T*)(mData)
通过混合使用static\u cast
、const\u cast
和reinterpret\u cast
因此,由于const_cast
和static_cast
不能在不相关的类型之间进行强制转换,因此这一行等同于:return*reinterpret_cast(mData)
此代码访问重新解释的结果,要求给定的动态类型
为字节
,别名类型
为T
:
AliasedType
是(可能是cv限定的)DynamicType
AliasedType
和DynamicType
都是指向同一类型的指针(可能是多级的,也可能是每个级别的cv限定值)
AliasedType
是DynamicType
的变体(可能是cv限定)signed
或unsigned
AliasedType
是一种聚合类型或union
类型,它将上述类型之一作为元素或非静态成员(递归地包括子聚合的元素和包含的联合的非静态数据成员)保存:这使得在给定指向其非静态成员或元素的指针时,可以安全地获取指向结构
或联合
的可用指针
AliasedType
是DynamicType
的基类(可能是cv限定的),而DynamicType
是一个没有非静态数据成员的标准布局类,AliasedType
是其第一个基类
AliasedType
是char
、无符号char
或std::byte
:这允许检查任何对象作为字节数组的对象表示形式
如果T
满足其中一种规范,则您的代码是无趣的,无法从一种类型转换为另一种类型,但它是合法的。如果不满足,则您的代码引入了未定义的行为,应被视为有毒的。return*reinterpret_cast(mData);
(在本例中T
是int
)是未定义的行为-您的编译器可能有一个扩展以使其实现定义,您需要检查。将reinterpret_cast替换为std::memcpy以修复。提示:@RichardCritten我会将其更改为常规c cast*(T*)(mData)查找正则C的内容,它仍然是UB。参见::使用MeMCPY将值放入数组中,需要使用MeMCPY来获得它。你称之为“正则”的转换没有任何更好的内容,而C++的Casic应该是不知道的。要分配一个数组:<代码>无符号char A(4)。
并将其强制转换为4字节整数也会导致您提到的硬件出现SEGFULT?@Brian:是的,字符数组(作为本地变量或全局变量)不能保证与其他数据类型对齐。您需要分配int
或int[]
如果您想获得一个地址,该地址肯定与int
s正确对齐。另一个选项是使用malloc
,另一方面,它保证地址对最严格的数据类型有效。好的,谢谢您的帮助。我刚刚了解了严格的别名规则。