将(n个第一个字节)无符号字符指针转换为浮点数和双精度C++

Posted

技术标签:

【中文标题】将(n个第一个字节)无符号字符指针转换为浮点数和双精度C++【英文标题】:convert (n first bytes of) unsigned char pointer to float and double c++ 【发布时间】:2018-09-19 16:20:55 【问题描述】:

考虑以下 c++ 代码:

unsigned char* data = readData(..);        //Let say data consist of 12 characters
unsigned int dataSize = getDataSize(...);  //the size in byte of the data is also known (let say 12 bytes)

struct Position 

   float pos_x;    //remember that float is 4 bytes
   double pos_y;   //remember that double is 8 bytes

现在我想用数据填充位置变量/实例。

Position pos;
pos.pos_x = ?   //data[0:4[ The first 4 bytes of data should be set to pos_x, since pos_x is of type float which is 4 bytes
pos.pos_x = ?   //data[4:12[ The remaining 8 bytes of data should be set to pos_y which is of type double (8 bytes)

我知道在data 中,第一个字节对应于pos_x,其余字节对应于pos_y。这意味着应该使用数据的第 4 个字节/字符来填充 pos_x,剩余的 8 个字节填充 pos_y,但我不知道该怎么做。 任何的想法?谢谢。 ps:我只限于c++11

【问题讨论】:

看看atof()/ atod @πάνταῥεῖ:不,他的数据以二进制形式存储,这些函数对文本进行操作。 memcpy 是您的问题的解决方案,如果来自 readData 的字节顺序与您的处理器本机字节顺序匹配。如果没有,您可以交换字节然后memcpy @BenVoigt 只需为此创建 net_to_host_memcpy 函数并以成员方式应用它。忘记交换字节。 @MaximEgorushkin:不行,因为你不知道有多少字节是倒序的。 (因此有单独的 htonshtonl 函数,而不仅仅是通用的“全部交换”) 【参考方案1】:

您可以使用普通的memcpy 作为另一个答案的建议。我建议将 memcpy 打包到一个函数中,该函数还可以为您进行错误检查,以实现最方便和类型安全的使用。

例子:

#include <cstring>
#include <stdexcept>
#include <type_traits>

struct ByteStreamReader 
    unsigned char const* begin;
    unsigned char const* const end;

    template<class T>
    operator T() 
        static_assert(std::is_trivially_copyable<T>::value, 
            "The type you are using cannot be safely copied from bytes.");
        if(end - begin < static_cast<decltype(end - begin)>(sizeof(T)))
            throw std::runtime_error("ByteStreamReader");
        T t;
        std::memcpy(&t, begin, sizeof t);
        begin += sizeof t;
        return t;
    
;

struct Position 
   float pos_x;
   double pos_y;
;

int main() 
    unsigned char data[12] = ;
    unsigned dataSize = sizeof data;

    ByteStreamReader readerdata, data + dataSize;

    Position p;
    p.pos_x = reader;
    p.pos_y = reader;

【讨论】:

一个迂腐的注解:memcpy 不能保证在全局命名空间中声明,除非您包含 &lt;string.h&gt;&lt;cstring&gt; 仅保证声明 std::memcpy @user2079303 点数。 您对转换运算符的使用有点危险。它实际上并没有将阅读器“转换”为数据。我可能对从具有&amp;&amp; 限制的名称的函数返回的临时对象执行此操作,但是在某些永久对象上?另外,你应该 static_assert 被复制的对象是合法的,通过 memcpy 创建。 static_assert( std::is_trivially_copyable&lt;T&gt;::value, "The type you are using cannot be safely copied from bytes." ) @Yakk-AdamNevraumont 不错。【参考方案2】:

您可以做的一件事是逐字节复制数据。有一个标准函数可以做到这一点:std::memcpy。示例用法:

assert(sizeof pos.pos_x == 4);
std::memcpy(&pos.pos_x, data, 4);
assert(sizeof pos.pos_y == 8);
std::memcpy(&pos.pos_y, data + 4, 8);

请注意,仅当数据与 CPU 使用的表示形式相同时,简单地复制数据才有效。了解不同的处理器使用不同的表示。因此,例如,如果您的readData 通过网络接收数据,则简单的副本不是一个好主意。在这种情况下,您至少要做的是将数据的字节序转换为本地字节序(可能来自大字节序,通常用作网络字节序)。从一种浮点表示转换为另一种表示要复杂得多,但幸运的是 IEE-754 相当普遍。

【讨论】:

您没有解释如何正确应用memcpy。由于sizeof(Position) == 16dataSize 是12。Position 中有填充 @MaximEgorushkin:可能有也可能没有填充,sizeof 可能是也可能不是16。为了便携性,最好正确处理填充。但最好不要对大小做出假设。 @MaximEgorushkin 我添加了一个例子。 @user2079303 非常感谢。我希望可以接受多个答案。因为你的回答也很好

以上是关于将(n个第一个字节)无符号字符指针转换为浮点数和双精度C++的主要内容,如果未能解决你的问题,请参考以下文章

opencv c++:将图像矩阵从无符号字符转换为浮点数

在汇编中将无符号字符转换为浮点数(为浮点向量计算做准备)

使用 AVX 的有符号/无符号整数的最小值

Python“ValueError:无法将字符串转换为浮点数:%”

将特征矩阵转换为无符号字符 *

ValueError:无法将字符串转换为浮点数:'n'