C++:将vector<char>转换为double

4

我正在使用vector<char>通过套接字发送和接收数据。在这个向量中,我存储了不同类型的数据。无符号整数和双精度浮点数。 为了从向量中解码数据,我正在使用copy函数。

vector<char> myVector = ... smth;
double value = 0.0;
copy(myVector.begin(), myVector.begin() + sizeof(value), &value);

它可以处理整数而没有问题。但是...
我的问题是,编译器会输出一个错误“free(): invalid pointer: 0x00000000006d0e30”。我检查了,问题在于双精度值,而不是向量。我查看了双精度值的地址,它是(0x6d0e38)。为什么程序要尝试向后访问指针?如果您能告诉我我做错了什么,那就太好了。这是否是解码消息的好方法?
非常感谢。

3
请发布所有失败的代码。请注意,sizeof(double) > sizeof(int)。不能依赖数据在接收端和发送端的字节序相同,因此,这不是一个好的设计。 - Steve Townsend
1
请检查您的向量大小,无论“但我知道这比sizeof(value)更大!” - BatchyX
@BatchyX:我也检查了向量的大小。在双精度值之后,存储了八个无符号整数。因此向量的大小为40(8 * 4 + 8)。 - M.K.
重申@BatchyX的评论,你应该在计算myVector.begin() + sizeof(value)之前验证myVector.size() <= sizeof(value) - Nemo
为了编写最可靠的代码,使用序列化库,例如Boost.Serialization或Google Protocol Buffers。如果您想自己编写,请封装好平台相关的代码,以避免维护方面的麻烦。 - Steve Townsend
显示剩余3条评论
3个回答

3
它可以在不出问题的情况下与整数一起使用。但是... 最好不要用于整型,尤其是对于 sizeof(int) > 1 的整型!因为它不仅会写入一个整数,而且还会将myVector 中的字节分散到sizeof(T)个整数中,从而覆盖随机内存(请参见nightcracker的答案)。这种复制最好使用memcpy 实现:
vector<char> myVector = ... smth;
double value = 0.0;
assert(myVector.size() == sizeof(double));
memcpy(&value, &myVector[0], std::min(myVector.size(), sizeof(double)));
// as an alternative to the assert + std::min() above, you could also throw
// an exception if myVector.size() == sizeof(double) does not hold.
// (that's what I'd do if the size should always match exactly)

memcpy的作用就是复制原始内存,这种情况下我认为没有理由使用其他方法。特别是当你使用std::copy时并不正确,这并不能使它成为更好的C++。std::copy是用于复制对象而非原始内存。


谢谢!我不知道。我以为C++的copy()只是C memcpy()的重新实现。 :) copy():“复制元素...”(http://www.cplusplus.com/reference/algorithm/copy/) 下次我应该更仔细地阅读。 - M.K.

2

我猜你需要根据需要转换指针,使 ptr++ 使用正确的大小(应该是 sizeof(char),而不是 sizeof(double)):

vector<char> myVector = ... smth;
double value = 0.0;
std::copy(myVector.begin(), myVector.begin() + sizeof(value),
    reinterpret_cast<char*>(&value));

嗯,我尝试了你的例子。编译没有出现错误信息。但是现在浮点值是错误的。它只是0. :-( - M.K.

2
不要这样做。通过套接字发送值的字符串表示形式。
std::stringstream ss;
double value = 0.0;
ss << value;

接下来使用ss.str()或者如果你真的需要一个字符向量:

std::vector<char> v(ss.begin(), ss.end());

-- 编辑 --
如果您确实需要保留数据的二进制格式,请执行以下操作

  std::vector<char> v(sizeof(double));
  double val = 0.5;
  std::memcpy(&v[0],(char*)&val,sizeof(val));
  ...
  double* out = (double*)&v[0];
  std::cout << *out << std::endl;

stringstream表示数据是二进制还是字符形式?我需要一个二进制流。 - M.K.
为什么要这样做?介绍了在类型之间转换数据,并且数据大小增加了两倍。另外stringstream还会带来额外的开销。原帖作者想要二进制数据。 - deceleratedcaviar
为什么需要二进制表示法?有很多原因你不想要它。如果接收者有不同的值表示方式(大/小端,16/32/64位...),会发生什么? - log0
@Ugo:我需要二进制数据,因为我的项目规格要求如此!!!(这不是我定的)根据规格,通信的所有方面都将使用LITTLE-ENDIAN。所以我不能使用stringstream :-( - M.K.
@Udo:我试过了,double类型的值是错误的。复制后的值为0.000...,而且缓冲区中有一些数据。因此它不可能是0。 - M.K.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接