C语言char强制类型转换unsigned int时的问题

来源:互联网 发布:淘宝能改店铺名称吗 编辑:程序博客网 时间:2024/04/30 10:12

今天做socket通信项目的时候要从数据包的包头计算图片长和宽,结果图片大小不对显示了一张大长脸,做个记录给自己提个醒。

图片高度,高度都用四个字节表示,数据包从第五位开始每四位依次是宽,高,想也没想就用了位运算,第一次写的代码是:

int mapwidth = 0;
int mapheight = 0;

wsabuf.buf是char类型

for(int i = 0; i <= 2; i ++)
mapwidth += ((unsigned int)wsabuf.buf[i + 4]) << (8 * (3 - i));
for(int i = 0; i <= 3; i ++)
mapheight += ((unsigned int)wsabuf.buf[i + 8]) << (8 * (3 - i));

进调试发现收到的数据包完全正确,高度对,宽度错,高度为1280,宽度四个字节数组依次是0,0,2,208,换算之后应该结果为256*2+208=720,但是结果为512,很明显最后一位没加上,所以想到会不会是左移0这个操作出现了错误,但是如果宽度错了为什么高度没错?仔细检查高度的数据包四个字节为0,0,5,0,最后一位是0所以左移0的操作应该没有影响,现在感觉是左移0这个操作有问题,做了个实验,在原来的代码前加了这几句话:

//////////test////////////
unsigned char a[4];
memcpy(a, &(wsabuf.buf[4]), 4);
unsigned int j = ((unsigned int)wsabuf.buf[7]) << 0;
/////////////////////

使用16进制数来看调试的结果:

数组a为:0x00,0x00,0x02,0xd0

j=0xff ff ff d0,

稍加改变,把j的数据类型换成int:

//////////test////////////
unsigned char a[4];
memcpy(a, &(wsabuf.buf[4]), 4);
int j = ((unsigned int)wsabuf.buf[7]) << 0;
/////////////////////

结果依然没变

好奇心比较重,假设这个j为0x00 00 02 00,那么会是什么样的结果呢?

int j = (0x00000200) << 0;

调试的结果为0x00 00 02 00。

若j=0x00 00 02 d0,那么运行的结果还是0x00 00 20 d0

看来我的感觉是错误的,左移0确实就是代表着所有数据位站着不动,那么问题就锁定在了((unsigned int)wsabuf.buf[7]) 强制类型转换上

wsabuf.buf是char类型,但是之前为了方便观察一直看数组a,数组a是个unsigned char,把int j = ((unsigned int)wsabuf.buf[7]) << 0;这句话改成:

int j = ((unsigned int)a[3]) << 0;运行结果正确,把char强制类型转换成unsigned int的时候,0xd0二进制数为1101 0000,十进制数为-48,最高位为1,所以当强制类型转换的时候所有位都填充1就变成了0x ff ff ff d0。

强制类型转换由字节比较小的数向字节比较大的数转化,当小数和大数都是有符号或者都没符号或者大数有符号的话,我们要保证他们最后表示的十进制数结果一致,比如上面char类型的数值为-48,转化成int类型的也要为-48,unsigned char如果十进制为208,转成的int十进制结果也要为208;如果符号不一致转 unsigned int看char的最高位,最高为为1全填充1,否则全填充0。强制类型转换的原则应该是尽量保证10进制数结果是正确的,而不是2进制的原码,个人理解,希望大神指点。