C语言32位无符号整型解包为4字符时前两字符不显示问题
问题根因
解包逻辑里右移位数计算错误,是导致前两个字符解析为0的直接原因。
32位无符号整数存储4个单字节字符时,4个字符从最高位到最低位的排布如下(按位从高到低,即bit31到bit0):
- 第一个字符a:占据bit24~bit31,对应掩码
0xFF000000(即定义的mask1=4278190080) - 第二个字符b:占据bit16~bit23,对应掩码
0x00FF0000(即定义的mask2=16711680) - 第三个字符c:占据bit8~bit15,对应掩码
0x0000FF00(即定义的mask3=65280) - 第四个字符d:占据bit0~bit7,对应掩码
0x000000FF(即定义的mask4=255)
按位与操作只能保留对应位置的位、将其他位置清0,必须把保留下来的位移到最低8位,才能正确存入char类型(char是单字节类型,赋值时只会保留最低8位的值)。当前代码里所有掩码匹配后的结果统一右移8位:
- a和mask1与后的结果是
(pack值 & 0xFF000000),仅右移8位后有效位落在bit16~bit23区间,赋值给char时最低8位全为0,因此输出空 - b和mask2与后的结果是
(pack值 & 0x00FF0000),仅右移8位后有效位落在bit8~bit15区间,赋值给char时最低8位全为0,因此输出空 - c和mask3与后的结果右移8位刚好落在最低8位,d不需要移位,因此后两个字符解析正常。
以输入的pack值1818978115为例,转十六进制为0x6C6B6743:
(0x6C6B6743 & 0xFF000000) >>8 = 0x006C0000,最低8位为0,赋值给a得到0(0x6C6B6743 & 0x00FF0000) >>8 = 0x00006B00,最低8位为0,赋值给b得到0(0x6C6B6743 & 0x0000FF00) >>8 = 0x00000067,对应ASCII字符'g'0x6C6B6743 & 0x000000FF = 0x00000043,对应ASCII字符'C'
和实际运行的现象完全一致。
修复方案
修改unpackCharacters32函数里的右移位数,每个掩码匹配后的结果右移对应位数,将有效位移到最低8位即可,修正后的函数代码如下:
void unpackCharacters32(char *aPtr, char *bPtr, char *cPtr, char *dPtr, unsigned int pack) { unsigned int mask1=4278190080; // 第一个字符掩码(bit24~31) unsigned int mask2=16711680; // 第二个字符掩码(bit16~23) unsigned int mask3=65280; // 第三个字符掩码(bit8~15) unsigned int mask4=255; // 第四个字符掩码(bit0~7) *aPtr = (pack & mask1)>>24; // 最高位字节右移24位到最低8位 *bPtr = (pack & mask2)>>16; // 次高位字节右移16位到最低8位 *cPtr = (pack & mask3)>>8; // 次低位字节右移8位到最低8位 *dPtr = (pack & mask4); // 最低位字节不需要移位 }
修正后运行,输入1818978115即可得到预期输出'l','k','g'和'C'。
补充说明:如果编译环境下char默认是有符号类型,传参给
displayBits时可能出现符号扩展导致高位显示异常,可在调用时将char强转为unsigned char,或直接把displayBits的参数类型改为unsigned char适配单字节场景。
内容的提问来源于stack exchange,提问作者Light
相关产品推荐
相关产品推荐

