将(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:不行,因为你不知道有多少字节是倒序的。 (因此有单独的 htons
和 htonl
函数,而不仅仅是通用的“全部交换”)
【参考方案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
不能保证在全局命名空间中声明,除非您包含 <string.h>
。 <cstring>
仅保证声明 std::memcpy
。
@user2079303 点数。
您对转换运算符的使用有点危险。它实际上并没有将阅读器“转换”为数据。我可能对从具有&&
限制的名称的函数返回的临时对象执行此操作,但是在某些永久对象上?另外,你应该 static_assert 被复制的对象是合法的,通过 memcpy 创建。
static_assert( std::is_trivially_copyable<T>::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) == 16
和dataSize
是12。Position
中有填充
@MaximEgorushkin:可能有也可能没有填充,sizeof
可能是也可能不是16
。为了便携性,最好正确处理填充。但最好不要对大小做出假设。
@MaximEgorushkin 我添加了一个例子。
@user2079303 非常感谢。我希望可以接受多个答案。因为你的回答也很好以上是关于将(n个第一个字节)无符号字符指针转换为浮点数和双精度C++的主要内容,如果未能解决你的问题,请参考以下文章