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
,另一方面,它保证地址对最严格的数据类型有效。好的,谢谢您的帮助。我刚刚了解了严格的别名规则。