【问题标题】:c++: convert vector<char> to doublec ++:将vector<char>转换为double
【发布时间】:2011-06-20 20:59:13
【问题描述】:

我正在使用vector&lt;char&gt; 通过套接字发送和接收数据。在这个向量中,我存储了不同类型的数据。无符号整数和双精度数。 要解码来自向量的数据,我使用copy 函数。

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

它可以毫无问题地与整数一起使用。但是……

我的问题是,编译给出了一个错误"free(): invalid pointer: 0x00000000006d0e30"。我查了一下,问题出在双精度值上,而不是向量上。我查看了它的双值地址(0x6d0e38)。为什么程序试图向后访问指针? 如果你能说我做错了什么,我会很高兴。它是解码消息的好方法吗?

非常感谢。

【问题讨论】:

  • 发布所有失败的代码。请注意sizeof(double) &gt; sizeof(int)。不能依赖接收端和发送端数据的字节序相同,所以不,这不是一个好的设计。
  • 请检查你的向量的大小,不管“但我知道这不仅仅是 sizeof(value) !”
  • 这只是一个错误。在此消息之后,我只有一长串 Qt 库(Backtrace)。是的,我知道 double 比 int 大。当我对 vector 进行编码时,我采用了 double 的整个大小。
  • @BatchyX:我也检查了向量的大小。在 double 值之后存储了八个无符号整数。所以向量的大小是40。(8*4 + 8)。
  • 重申@BatchyX 的评论,您应该在计算myVector.begin() + sizeof(value) 之前验证myVector.size() &lt;= sizeof(value)

标签: c++ vector buffer


【解决方案1】:

它可以毫无问题地与整数一起使用。但是……

它肯定适用于整数。至少不适用于 sizeof(int) &gt; 1! 的整数。因为它不会只写入一个整数,而是将myVector 中的字节分布在sizeof(T) 整数上,从而覆盖随机内存。 (见夜莺的回答)

请使用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(): "Copies the elements..." (cplusplus.com/reference/algorithm/copy) 下次我应该仔细阅读。
【解决方案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。:-(
【解决方案3】:

不要这样做。通过套接字发送值的字符串表示形式。

std::stringstream ss;
double value = 0.0;
ss << value;

然后使用 ss.str() 或者如果你真的需要一个 char 向量:

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;

【讨论】:

  • 字符串流是以二进制还是字符形式表示数据?我需要一个二进制流。
  • 你为什么要这样做?介绍了类型之间的数据转换,并且是以字节为单位的数据的两倍。加上字符串流开销。 OP 想要二进制文件。
  • 为什么需要二进制表示?你不想要这个有很多原因。如果接收者有不同的方式来表示值会发生什么(大/小端,16/32/64位......)
  • @Ugo:由于我的项目规范,我需要二进制数据!!! (这不是我的)根据规范,通信的所有方面都将使用 LITTLE-ENDIAN。所以我不能使用 stringstream :-(
  • @Udo:我试过了。 double 的值是错误的。复制后的值为 0.000... 并且缓冲区中有一些数据。所以它不可能是 0。
猜你喜欢
  • 1970-01-01
  • 2018-09-23
  • 2014-11-19
  • 2014-05-16
  • 1970-01-01
  • 2013-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多