将大字节序的float数据直接复制到vector <float>中,并就地进行字节交换。安全吗?

埃米尔·科米尔(Emile Cormier)

我希望能够将大字节序float数组直接从未对齐的网络缓冲区复制到,std::vector<float>并执行字节交换回主机顺序“就地”,而无需涉及中间过程std::vector<uint32_t>这样安全吗?我担心大字节序浮点数据可能会意外地解释为NaN并触发意外行为。这是一个有效的关注吗?

出于此问题的目的,假定接收数据的主机为低端字节序。

这是一些代码,展示了我正在尝试做的事情:

std::vector<float> source{1.0f, 2.0f, 3.0f, 4.0f};
std::size_t number_count = source.size();

// Simulate big-endian float values being received from network and stored
// in byte buffer. A temporary uint32_t vector is used to transform the
// source data to network byte order (big endian) before being copied
// to a byte buffer.
std::vector<uint32_t> temp(number_count, 0);
std::size_t byte_length = number_count * sizeof(float);
std::memcpy(temp.data(), source.data(), byte_length);
for (uint32_t& datum: temp)
    datum = ::htonl(datum);
std::vector<uint8_t> buffer(byte_length, 0);
std::memcpy(buffer.data(), temp.data(), byte_length);
// buffer now contains the big endian float data, and is not aligned at word boundaries

// Copy the received network buffer data directly into the destination float vector
std::vector<float> numbers(number_count, 0.0f);
std::memcpy(numbers.data(), buffer.data(), byte_length); // IS THIS SAFE??

// Perform the byte swap back to host order (little endian) in place,
// to avoid needing to allocate an intermediate uint32_t vector.
auto ptr = reinterpret_cast<uint8_t*>(numbers.data());
for (size_t i=0; i<number_count; ++i)
{
    // IS THIS SAFE??
    uint32_t datum;
    std::memcpy(&datum, ptr, sizeof(datum));
    *datum = ::ntohl(*datum);
    std::memcpy(ptr, &datum, sizeof(datum));
    ptr += sizeof(datum);
}

assert(numbers == source);

注意两个“这很安全吗?” 上面的评论。

动机:我正在编写一个支持类型数组的CBOR序列化库CBOR允许类型化数组以大端或小端的形式传输。

编辑:替换reinterpret_cast<uint32_t*>字节序在endian交换循环中的非法类型memcpy

安德烈亚斯(Andreas H.)

编辑后:

关于auto datum = reinterpret_cast<uint32_t*>(numbers.data());:这在C ++中是不允许的,只能安全地对它进行类型双打uint8_t(仅当CHAR_BIT == 8时,更确切地说,此类型双工异常仅适用于char类型)

旧答案:以下是编辑之前的问题(带有的问题bit_cast)。

只要提供,这是安全的 sizeof(float) == sizeof(uint32_t)

不必担心会发出NaN信号。通常会禁用这些例外,即使启用了例外,它们也只会在生成信号NaN时发生。移动指令不会产生异常。

data()支持通过指针访问矢量元素(用于读取和写入)。vector保证有连续的存储。

但是,为什么不在没有临时缓冲区的情况下仅在一个循环中完成所有操作?

仅具有浮点向量(输入或输出)和数据缓冲区(uint8_t向量)。为了仅在float输入向量上发送迭代,请对每个元素执行字节交换并将4个字节写入数据缓冲区。一次一个。这样就不需要任何中间缓冲区。它可能不会变慢。对于接收,请执行相反的操作。

采用std::bit_cast浮法转换自/至std::array<uint8_t,4>这将是C ++ 20中的“正确”方式(您不能直接在bit_cast中使用C数组)。使用这种方法,您无需调用ntohl,只需按正确的顺序将字节从缓冲区复制到缓冲区即可。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

PowerShell:将十六进制变量转换为单个(float32)大字节序变量

如何将byte []数据复制到很大的float []中?

将数据从 float* 传输/复制到 vector<float> 的最快方法

将数据从 float* 传输/复制到 vector<float> 的最快方法

将数据从 float* 传输/复制到 vector<float> 的最快方法

在CUDA中从float *到float3 *的转换安全吗?

将Float32Array复制到Safari和Edge中的新AudioBuffer

将字节序列转换为浮点序列F#(seq <seq <byte>-> seq <seq <float>)

反向二进制文件中的float32字节序的快速方法

python 2.7-将float转换为字节并遍历字节

将n个字节的数据x复制到文件

C中的大字节序字节数组到小字节序结构元素

将多个字节数组复制到一个大字节数组

我可以在C ++中安全地将float的结构转换为float数组吗?

将字节数组直接复制到Java中的剪贴板中

如何将 float* 复制到 IntPtr?

std :: copy将double数组复制到float数组?

将数据从较小的 AudioBuffers 复制到较大的 Float32Array

在Python中序列化float是安全的吗?

不安全的C#:如何将数据从IntPtr复制到字节*?

将字节转换为float是安全的还是会产生未定义的行为?

如何使用ctypes将字节转换为float?

如何将float转换为字节数组?

JavaScript-以干净的方式将字节转换为float

将字节数组转换为float32

大字节序,小字节序转换

float1 vs CUDA中的float

将文件从地址字节复制到地址字节

将 float 除以 int 总是给 float 吗?C++