在 C 或 C++ 中, uint64_t 的内存布局是否保证与 uint32_t[2] 相同?一个可以扮演另一个吗?

In C or C++, is memory layout of uint64_t guaranteed to be the same as uint32_t[2] ? Can one be cast as the other?

在 C 或 C++ 中,uint64_t 的内存布局是否保证与 uint32_t[2] 相同?我可以将一个投射到另一个并让它们始终按预期工作吗?它取决于 CPU 是 32 位还是 64 位,还是取决于编译器实现?

In C or C++, is memory layout of uint64_t guaranteed to be the same as uint32_t[2] ?

没有。字节顺序。

Can one be cast as the other?

可能,也可能不是,在 C 中。指向 2 uint32_t 的数组的指针可能未与 uint64_t 对齐。当生成的指针未正确对齐时,它是未定义的行为。 https://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p7

在 C++ 中是的。 https://eel.is/c++draft/expr#reinterpret.cast-7

Can I cast one to the other and have them always work as expected?

没有。可能,您可以转换,但转换后您不能访问 带有句柄的数据。这将是一个严格的别名违规。

Does it depend upon if the CPU is 32bit or 64bit

不是真的。

or is it compiler implementation dependent?

因为行为是未定义的,所以它在很大程度上依赖于编译器。

至少从 C++20 开始,C++ 中就没有特殊的整数值(我认为,与 C 相反,它们在理论上仍然存在),因此两个相邻 uint32 对象的所有位组合形成一个有效的 64 位整数位序列。

由于别名和潜在的对齐问题,转换指针仍然是不允许的,但在 C++20 中,您可以使用 std::bit_cast() 获取原始对象的按位副本:uint32_t arr[2] = {}; uint64_t ui64 = std::bit_cast<uint64_t>(arr);。请注意,这会执行复制。

正如卡米尔所说,结果在小端系统上可能令人惊讶,但它是有效的。

有一个小时长,中等有趣 CppCon talk about type punning by Timur Doumler on youtube. 52 minutes into the talk 他将无法将字节解释为不同类型称为“C++ 对象模型中的最后一个漏洞”,并表示他将编写一个修复建议它通过引入等价于 alignas,例如layoutas(T) 告诉编译器接受解释为 T.