我有一个二进制数组char buffer[N];
,它包含两个字节,在其开头被解释为unsigned short,并且当前正在通过
unsigned short size= 0;
memcpy((char *) &size, buffer, sizeof(unsigned short));
但是我想为此使用std :: copy。这可能吗?
尝试
std::copy(buffer, buffer+sizeof(unsigned short), (char *) &size);
编译时导致各种错误。
编辑抱歉,我匆忙忘了:
这是在具有gcc 4.4.3的Ubuntu GNU / Linux系统上。错误消息为Error: Invalid conversion from ‘char*’ to ‘char’
。
答案 0 :(得分:6)
您不应该为此使用任何类型的批量复制例程,也不应该使用类型转换来获取指向unsigned short
的指针,因为这些选项都不会考虑字节顺序。从char[]
缓冲区中提取双字节无符号整数的正确方法是使用以下函数之一:
unsigned short extract_littleend16(const unsigned char *buf)
{
return (((unsigned short)buf[0]) << 0) |
(((unsigned short)buf[1]) << 8);
}
unsigned short extract_bigend16(const unsigned char *buf)
{
return (((unsigned short)buf[0]) << 8) |
(((unsigned short)buf[1]) << 0);
}
std::copy
,memcpy
和直接指针抨击都会与一个这些函数做同样的事情,但你不知道它是哪一个将会,并且每当你完成这项任务时,其中一个功能是正确的而另一个是错误的。此外,如果你不知道从上下文中需要哪一个,那就去几个设计级别并找出它。
答案 1 :(得分:4)
你实际上根本不需要使用任何副本,这就是真正指针的美妙之处。 例如,在基于Windows的系统上,您可以只使用这行代码。 尝试
size = *((unsigned short *)buffer);
std :: copy需要迭代器,为此,我会坚持使用memcpy afterall
答案 2 :(得分:2)
size = *(unsigned short*)buffer;
应该做; - )
答案 3 :(得分:2)
好的,我的回答有点澄清:
你可以这样做,应该* 编译 * 没有问题,请参阅下面的代码。但是,你真的不想这样做,因为它有一些警告。
1:如果本地字节顺序与char缓冲区中的字节顺序不同,它将会很糟糕(参见4,由于Zack而导致的学分 - 我自己错过了这一点)。
2:如果你搞砸了演员阵容,你将最终处于未定义的行为中(请参阅帖子上的评论,我首先错过了指定演员)
3。:STL的调试实现可能会发出警告,或者完全阻止您编译这样的代码(并且出于某种原因这样做)。
4:它可能会编译并且似乎运行良好,但它不一定按照您的意图执行(参见2.)
5:我确信还有更多:)
这是编译示例(i686-apple-darwin11-llvm-gcc-4.2)。使用风险自负。
#include <algorithm>
#include <iostream>
int main()
{
unsigned short foo = 0;
char byte[2] = { 0x10, 0xFF };
// WARNING: This will screw up if the native byte order is different
// from the byte order in the buffer!!! (Credits: Zack)**
std::copy(byte, byte + sizeof(unsigned short), (char*)&foo);
std::cerr << foo << std::endl;
return 0;
}