C++ std::array';的这个并集的公共初始序列有问题吗;s

C++ std::array';的这个并集的公共初始序列有问题吗;s,c++,unions,C++,Unions,对纪尧姆·拉西科特的评论感到困惑。这里有问题吗?至少在GCC 10.1 x86-64(-O3--std=c++20-pedantic-Wall-Werror)中,我写。字,读。字节 sizeof(MyUnion)==32也令人放心 union MyUnion { static constexpr std::size_t size = 32; using byte = std::uint8_t; using word = std::uint32_t; s

对纪尧姆·拉西科特的评论感到困惑。这里有问题吗?至少在GCC 10.1 x86-64(
-O3--std=c++20-pedantic-Wall-Werror
)中,我写
。字
,读
。字节

sizeof(MyUnion)==32也令人放心

union MyUnion {
    static constexpr std::size_t size = 32;

    using byte = std::uint8_t;
    using word = std::uint32_t;
    
    std::array<byte, size> bytes;
    std::array<word, size / sizeof(word)> words;
};
static_assert(sizeof(MyUnion)==32);
union我的union{
静态constexpr std::size\u t size=32;
使用byte=std::uint8\u t;
使用word=std::uint32\u t;
std::数组字节;
std::数组字;
};
静态断言(sizeof(MyUnion)==32);
标准规定:

[数组.概述]

。。。数组是一个连续的容器

数组是一个聚合,最多可以用N个类型可转换为T的元素进行列表初始化

如果T是结构类型,则数组是结构类型

该标准没有明确说明成员
std::array
拥有什么。因此,我们在技术上不能假设它具有任何类型的公共初始序列

根据
std::array
上显示的要求,我们可以合理地假设它有一个
T[N]
类型的成员。如果这个假设是正确的,我们来探讨是否存在一个共同的初始序列

[类别成员概述]

两个标准布局结构([class.prop])类型的公共初始序列是按声明顺序排列的非静态数据成员和位字段的最长序列,从每个结构中的第一个这样的实体开始,这样相应的实体就具有布局兼容的类型

[基本.类型.概述]

如果T1和T2是相同的类型、布局兼容的枚举或布局兼容的标准布局类类型,则两种类型cv1 T1和cv2 T2是布局兼容的类型

std::uint8_t[32]
std::uint32_t[8]
不是同一类型(忽略cv限定符),它们也不是枚举或类。因此,它们不是与布局兼容的类型,因此它们不能是同一公共初始序列的一部分

结论:不,无论我们是否能够安全地假定
std::array
的成员,都没有共同的初始序列


我写。字和读。字节

程序的行为未定义

鉴于您希望将其读取为(无符号)字符数组,因此可以安全地重新解释,而不是联合双关:

static constexpr std::size_t size = 32;
using word = std::uint32_t;
std::array<word, size / sizeof(word)> words {
    1, 2, 3, 4,
};
std::uint8_t* bytes = reinterpret_cast<std::uint8_t*>(words.data());
static constexpr std::size\u t size=32;
使用word=std::uint32\u t;
数组字{
1, 2, 3, 4,
};
std::uint8_t*bytes=重新解释强制转换(words.data());
如果您想要一个范围:

std::span<std::uint8_t, size> bytes_range {
    bytes, bytes + size,
};
std::span字节\u范围{
字节,字节+大小,
};

GCC。自从OP提到GCC,程序在这个例子中没有被定义。@ BESC我从C++语言的角度写了答案。如果一个语言实现选择为UB定义一个行为,它可以自由地这样做——这将是一个语言扩展。您的链接似乎指向了关于其C实现的GCC文档。它是否也适用于C++实现?对于这个特定用例,CAN()可以被认为是优于代码> RealTytCase<代码>的替代方案吗?(尚未提供)。@Xpector它的优劣取决于用例。它创建一个新对象,而不是解释现有对象。但是它可以被用在更多的情况下,而只有在非常有限的例外情况下才允许重新解释。@ ErRika从C++语言的角度来看,你的答案是完全好的,毫无疑问。我只是认为GCC的特殊行为是一个有用的补充,因为OP特别提到了GCC。该规则也适用于C++。C++ DOCS链接到C文档中的那个地方。我现在似乎找不到C++文档中的那个地方,但我最近读过。