考虑以下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
答案 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;
}