将无符号字符指针(的前n个字节)转换为float和double c ++

时间:2018-09-19 16:20:55

标签: c++ c++11 pointers

考虑以下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变量/实例。

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

2 个答案:

答案 0 :(得分:3)

您可以做的一件事是逐字节复制数据。有一个标准函数可以执行此操作: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相当普遍。

答案 1 :(得分:3)

您可以使用普通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 reader{data, data + dataSize};

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