近期调串口通信时,碰到了有符号和无符号数转换问题,在此小结下:
关于“无符号负数”的显示
所谓“无符号负数” :这里是指将负数赋值给无符号类型变量
负数,无论是赋值给有符号数,还是无符号数,内存中二进制的表示形式是一样的;显示成有符号还是无符号,是根据printf的格式化参数来决定的。
%d是按照有符号输出,%u是按照无符号输出。
u_int32_t a = -100;
u_int32_t b = u_int32_t(-100);
printf("a = %d !\n", a);
printf("b = %d !\n", b);
printf("u = %u !\n", a);
printf("u = %u !\n", b);
//输出:
a = -100 !
b = -100 !
u = 4294967196 !
u = 4294967196 !
用unsigned定义变量,在C语言运算时有用。譬如位移运算,无符号数右移时,高位补充0,如果是有符号数右移,高位补充的是符号位的值(负数的符号位是1,正数的符号位是0)。
关于负数的二进制表示:
在二进制码中,为了区分正负数,采用最高位是符号位的方法来区分,正数的符号位为0、负数的符号位为1。剩下的就是这个数的绝对值部分,可以采用原码、反码、补码3种形式来表示绝对值部分。
但对于二进制运算而言,原码的运算不够方便,当两个数相加时,先要判断这两个数的符号是否相同,符号不同的话,还要判断哪一个数的绝对值更大。所以在计算机中,通常都是采用补码形式。正整数的补码与原码形式相同,例如+7的8位二进制补码是00000111;而负整数的补码则可以通过下列方式得到:将这个负整数的绝对值求反加1,连同符号位1一起表示就可以了。例如-7的8位二进制补码:将-7的绝对值7求反加1得1111001,连同符号位1一起就是11111001。
关于“无符号 负数”的类型转换问题:
位运算 丢失符号位:
u_int32_t c = -100;
u_int16_t d_16 = (c & 0xFF00);
printf("c = %d !\n", c);
printf("d_16 = %d !\n", d_16);
//输出:
c = -100 !
d_16 = 65280 !//负数的低16位和0xFF00与运算,结果赋值给d_16;丢失了符号位,所以很大。
截断,丢失符号位:
u_int32_t c = -100;
u_int16_t e_16 = c;
printf("e_16 = %d !\n", e_16);
//输出
e_16 = 65436 ! //发生截断,丢失了符号位,所以很大。
2917

被折叠的 条评论
为什么被折叠?



