C++;:如何将数组中的2个字节强制转换为无符号短字符 我一直致力于一个传统的C++应用程序,而且绝对超出了我的舒适范围(好事情)。我想知道是否有人愿意给我一些建议(双关语)
我需要将无符号字符数组中的2个字节强制转换为无符号短字符。字节是连续的 例如,我正在尝试做什么: 我从套接字接收字符串,并将其放入无符号字符数组中。我可以忽略第一个字节,然后将接下来的2个字节转换为无符号字符。这将只在windows上进行,因此没有大/小的Endian问题(我知道) 以下是我现在的情况(显然不起作用):C++;:如何将数组中的2个字节强制转换为无符号短字符 我一直致力于一个传统的C++应用程序,而且绝对超出了我的舒适范围(好事情)。我想知道是否有人愿意给我一些建议(双关语),c++,pointers,casting,C++,Pointers,Casting,我需要将无符号字符数组中的2个字节强制转换为无符号短字符。字节是连续的 例如,我正在尝试做什么: 我从套接字接收字符串,并将其放入无符号字符数组中。我可以忽略第一个字节,然后将接下来的2个字节转换为无符号字符。这将只在windows上进行,因此没有大/小的Endian问题(我知道) 以下是我现在的情况(显然不起作用): //packetBuffer是一个无符号字符数组,包含用于测试的字符串“123456789” //我需要将字节2和3转换为短字节,2是最重要的字节 //所以我希望得到515(2*
//packetBuffer是一个无符号字符数组,包含用于测试的字符串“123456789”
//我需要将字节2和3转换为短字节,2是最重要的字节
//所以我希望得到515(2*256+3),而不是我尝试过的所有代码
//错误或2(仅转换一个字节
未签名的短myShort;
myShort=static_cast(packetBuffer[1])
静态强制转换有不同的语法,加上您需要使用指针,您要做的是:
unsigned short *myShort = static_cast<unsigned short*>(&packetBuffer[1]);
unsigned short*myShort=static_cast(&packetBuffer[1]);
这可能远低于您所关心的,但请记住,这样做很容易获得未对齐的访问。x86是可以原谅的,未对齐的访问导致的中止将在内部捕获,并最终复制并返回值,因此您的应用程序不会知道任何不同但是,如果此代码将在非x86上运行(您没有提到目标平台,所以我假设是x86桌面窗口),那么这样做将导致处理器数据中止,您必须在尝试强制转换数据之前手动将数据复制到对齐的地址
简言之,如果您要经常进行这种访问,您可以考虑对代码进行调整,以避免未对齐的读取,这样您将看到性能优势。您不应该将无符号字符指针强制转换为无符号短指针(因此,从较小数据类型的指针强制转换为较大数据类型)。这是因为假定地址将正确对齐。更好的方法是将字节转换为实际的无符号短对象,或将memcpy转换为无符号短数组
毫无疑问,您可以调整编译器设置以绕过此限制,但如果代码被传递和重用,这是一件非常微妙的事情,将来会被打破。好吧,您正在将字符加宽为短值。您想要的是将两个字节解释为短值。
static\u cast
无法从unsi进行强制转换gned char*
到unsigned short*
。您必须强制转换到void*
,然后转换到unsigned short*
:
unsigned short *p = static_cast<unsigned short*>(static_cast<void*>(&packetBuffer[1]));
unsigned short*p=static_cast(static_cast(&packetBuffer[1]);
现在,您可以取消对p的引用并获得短值。但是这种方法的问题是,您从unsigned char*、void*转换为其他类型。标准不保证地址保持不变(此外,取消引用该指针将是未定义的行为).更好的方法是使用位移位,这将始终有效:
unsigned short p = (packetBuffer[1] << 8) | packetBuffer[2];
unsigned short p=(packetBuffer[1]没有人看到输入是字符串
/* If it is a string as explicitly stated in the question.
*/
int byte1 = packetBuffer[1] - '0'; // convert 1st byte from char to number.
int byte2 = packetBuffer[2] - '0';
unsigned short result = (byte1 * 256) + byte2;
/* Alternatively if is an array of bytes.
*/
int byte1 = packetBuffer[1];
int byte2 = packetBuffer[2];
unsigned short result = (byte1 * 256) + byte2;
这也避免了大多数其他解决方案在某些平台上可能存在的对齐问题。请注意,短指针至少有两个字节。如果您尝试取消引用未对齐两个字节的短指针(或系统上的(短)指针大小)!char packetBuffer[]={1, 2, 3};
无符号短myShort=*重新解释强制转换(&packetBuffer[1]);
我(不得不)一直这样做。big-endian是一个明显的问题。当机器不喜欢未对齐的读取(和写入)时,真正让你得到的是不正确的数据
您可能需要编写测试转换和断言,以查看其读取是否正确。因此,当在big-endian机器上运行时,或者更重要的是,在不喜欢未对齐读取的机器上运行时,将发生断言错误,而不是奇怪的难以跟踪的“错误”;)上面的位偏移有一个错误:
unsigned short p = (packetBuffer[1] << 8) | packetBuffer[2];
或者,为了节省一些时钟周期,并且不将位移离末端:
unsigned short p;
p = (((unsigned short)packetBuffer[1])<<8) | packetBuffer[2];
无法保证一个完全没有bug的编译器会创建您所期望的代码。字节数组b
发送到do\u something\u with()
函数可能永远不会被*s
操作修改。上面的代码中没有说明应该修改。如果不优化代码,则可能永远不会看到此问题(直到有人优化或更改编译器或编译器版本)。如果使用调试器,则可能永远不会看到此问题(直到为时已晚)
编译器看不到s和b之间的连接,它们是两个完全独立的项。优化器可能会选择不将*s
写回内存,因为它看到*s
有许多操作,因此它可以将该值保留在寄存器中,并且只在最后将其保存到内存中(如果有的话)
有三种基本方法可以解决上述指针问题:
将s
声明为易失性
使用工会
在更改类型时使用一个或多个函数
在windows上,您可以使用:
unsigned short i = MAKEWORD(lowbyte,hibyte);
我意识到这是一个古老的线程,我不能说我尝试了这里提出的每一个建议。我只是让自己对mfc感到舒服,我正在寻找一种方法,将uint转换为两个字节,然后再转换到套接字的另一端
你可以在网上找到很多位转移的例子,但它们似乎都不起作用。很多例子似乎过于复杂;我的意思是,我们只是说从uint中获取2个字节,然后发送
unsigned short p = (packetBuffer[1] << 8) | packetBuffer[2];
unsigned short p;
p = packetBuffer[1]; p <<= 8; p |= packetBuffer[2];
unsigned short p;
p = (((unsigned short)packetBuffer[1])<<8) | packetBuffer[2];
unsigned short *s;
unsigned char b[10];
s=(unsigned short *)&b[0];
if(b[0]&7)
{
*s = *s+8;
*s &= ~7;
}
do_something_With(b);
*s=*s+8;
do_something_With(b);
*s=*s+8;
do_something_With(b);
unsigned short i = MAKEWORD(lowbyte,hibyte);
class ByteConverter
{
public:
static void uIntToBytes(unsigned int theUint, char* bytes)
{
unsigned int tInt = theUint;
void *uintConverter = &tInt;
char *theBytes = (char*)uintConverter;
bytes[0] = theBytes[0];
bytes[1] = theBytes[1];
}
static unsigned int bytesToUint(char *bytes)
{
unsigned theUint = 0;
void *uintConverter = &theUint;
char *thebytes = (char*)uintConverter;
thebytes[0] = bytes[0];
thebytes[1] = bytes[1];
return theUint;
}
};
unsigned int theUint;
char bytes[2];
CString msg;
ByteConverter::uIntToBytes(65000,bytes);
theUint = ByteConverter::bytesToUint(bytes);
msg.Format(_T("theUint = %d"), theUint);
AfxMessageBox(msg, MB_ICONINFORMATION | MB_OK);
union CharToStruct {
char charArray[2];
unsigned short value;
};
short toShort(char* value){
CharToStruct cs;
cs.charArray[0] = value[1]; // most significant bit of short is not first bit of char array
cs.charArray[1] = value[0];
return cs.value;
}
char array[2];
array[0] = 0x00;
array[1] = 0x03;
short i = toShort(array);
cout << i << endl; // or printf("%h", i);