简体   繁体   English

带有 std::array 的 std::bit_cast

[英]std::bit_cast with std::array

In his recent talk “Type punning in modern C++” Timur Doumler said that std::bit_cast cannot be used to bit cast a float into an unsigned char[4] because C-style arrays cannot be returned from a function.在他最近的演讲“现代 C++ 中的类型双关语”中, Timur Doumlerstd::bit_cast不能用于将float位转换为unsigned char[4] ,因为不能从 function 返回 C 样式的 arrays。 We should either use std::memcpy or wait until C++23 (or later) when something like reinterpret_cast<unsigned char*>(&f)[i] will become well defined.我们应该使用std::memcpy或等到 C++23(或更高版本),当reinterpret_cast<unsigned char*>(&f)[i]类的东西将变得明确时。

In C++20, can we use an std::array with std::bit_cast ,在 C++20 中,我们可以将std::arraystd::bit_cast一起使用吗?

float f = /* some value */;
auto bits = std::bit_cast<std::array<unsigned char, sizeof(float)>>(f);

instead of a C-style array to get bytes of a float ?而不是 C 样式的数组来获取float的字节?

Yes, this works on all major compilers, and as far as I can tell from looking at the standard, it is portable and guaranteed to work.是的,这适用于所有主要的编译器,据我看标准,它是可移植的并且保证可以工作。

First of all, std::array<unsigned char, sizeof(float)> is guaranteed to be an aggregate ( https://eel.is/c++draft/array#overview-2 ).首先, std::array<unsigned char, sizeof(float)>保证是一个聚合( https://eel.is/c++draft/array#overview-2 )。 From this follows that it holds exactly a sizeof(float) number of char s inside (typically as a char[] , although afaics the standard doesn't mandate this particular implementation - but it does say the elements must be contiguous) and cannot have any additional non-static members.由此得出,它在内部精确地保存了sizeof(float)数量的char (通常作为char[] ,尽管 afaics 标准没有强制要求这种特定的实现 - 但它确实说元素必须是连续的)并且不能有任何其他非静态成员。

It is therefore trivially copyable, and its size matches that of float as well.因此它很容易复制,并且它的大小也与float相匹配。

Those two properties allow you to bit_cast between them.这两个属性允许您在它们之间进行bit_cast

The accepted answer is incorrect because it fails to consider alignment and padding issues.接受的答案不正确,因为它没有考虑 alignment 和填充问题。

Per [array]/1-3 :每个[array]/1-3

The header <array> defines a class template for storing fixed-size sequences of objects. header <array>定义了一个 class 模板,用于存储固定大小的对象序列。 An array is a contiguous container.数组是一个连续的容器。 An instance of array<T, N> stores N elements of type T , so that size() == N is an invariant. array<T, N>的实例存储了NT类型的元素,因此size() == N是一个不变量。

An array is an aggregate that can be list-initialized with up to N elements whose types are convertible to T .数组是一个聚合,可以使用最多N个元素进行列表初始化,这些元素的类型可以转换为T

An array meets all of the requirements of a container and of a reversible container ( [container.requirements] ), except that a default constructed array object is not empty and that swap does not have constant complexity.数组满足容器和可逆容器 ( [container.requirements] ) 的所有要求,除了默认构造的数组 object 不是空的并且交换没有恒定的复杂性。 An array meets some of the requirements of a sequence container.数组满足序列容器的一些要求。 Descriptions are provided here only for operations on array that are not described in one of these tables and for operations where there is additional semantic information.此处仅针对这些表之一中未描述的数组操作以及存在附加语义信息的操作提供描述。

The standard does not actually require std::array to have exactly one public data member of type T[N] , so in theory it is possible that sizeof(To) != sizeof(From) or is_trivially_copyable_v<To> .该标准实际上并不要求std::array恰好有一个T[N]类型的公共数据成员,因此理论上sizeof(To) != sizeof(From)is_trivially_copyable_v<To>是可能的。

I will be surprised if this doesn't work in practice, though.不过,如果这在实践中不起作用,我会感到惊讶。

Yes.是的。

According to the paper that describes the behaviour of std::bit_cast , and its proposed implementation as far as both types have the same size and are trivially copyable the cast should be successful.根据描述std::bit_cast行为的论文及其建议的实现,只要两种类型具有相同的大小并且可以轻松复制,强制转换应该是成功的。

A simplified implementation of std::bit_cast should be something like: std::bit_cast的简化实现应该类似于:

template <class Dest, class Source>
inline Dest bit_cast(Source const &source) {
    static_assert(sizeof(Dest) == sizeof(Source));
    static_assert(std::is_trivially_copyable<Dest>::value);
    static_assert(std::is_trivially_copyable<Source>::value);

    Dest dest;
    std::memcpy(&dest, &source, sizeof(dest));
    return dest;
}

Since a float (4 bytes) and an array of unsigned char with size_of(float) respect all those asserts, the underlying std::memcpy will be carried out.由于浮点数(4 字节)和带有size_of(float)unsigned char数组尊重所有这些断言,因此将执行底层std::memcpy Therefore, each element in the resulting array will be one consecutive byte of the float.因此,结果数组中的每个元素都将是浮点数的一个连续字节。

In order to prove this behaviour, I wrote a small example in Compiler Explorer that you can try here: https://godbolt.org/z/4G21zS .为了证明这种行为,我在 Compiler Explorer 中编写了一个小示例,您可以在此处尝试: https://godbolt.org/z/4G21zS The float 5.0 is properly stored as an array of bytes ( Ox40a00000 ) that corresponds to the hexadecimal representation of that float number in Big Endian .浮点数 5.0 正确存储为字节数组 ( Ox40a00000 ),对应于Big Endian中该浮点数的十六进制表示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 可以使用 std::bit_cast 从 std::span 转换<A>到 std::span<B>并像访问对象 B 一样访问吗?</a> - Can std::bit_cast be used to cast from std::span<A> to std::span<B> and access as if there was an array of object B? C++11 中 std::bit_cast 的安全等效项 - Safe equivalent of std::bit_cast in C++11 是否已经有一个 constexpr std::bit_cast 与 g++ 一起使用 - Is there already a constexpr std::bit_cast to use with g++ 通过 std::bit_cast()ed 指针对访问进行别名访问 - Aliasing accesses through a std::bit_cast()ed pointer std::bit_cast 和 std::start_lifetime_as 之间有什么有用的区别吗? - Any useful difference between std::bit_cast and std::start_lifetime_as? static_cast 之间有区别吗<unsigned> (有符号) vs std::bit_cast<unsigned> (签)? - Is there difference between static_cast<unsigned>(signed) vs std::bit_cast<unsigned>(signed)? 文件 I/O 中的 std::bit_cast 与 reinterpret_cast - std::bit_cast vs reinterpret_cast in file I/O std::bit_cast 生成多个值的值表示的示例是什么? - What would be an example where std::bit_cast produces a value representation of multiple values? C++20 特性 std::bit_cast:重新解释类型 from 到 type to 时值会发生什么 - C++20 feature std::bit_cast : what happens to the value while reinterpreting type from to type to `bit_cast` arrays 到 arrays - `bit_cast` arrays to arrays
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM