转载请注明出处 http://blog.csdn.net/dream_whui/article/details/45439831, 欢迎朋友们,做出批评指正,thanks~~
1. 原码
原码就是符号位加上真值的绝对值, 即用第一位表示符号,其余位表示值. 比如如果是8位二进制:
[+1]原 = 0000 0001
[-1]原 = 1000 0001
第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是:
[1111 1111 , 0111 1111]
即
[-127 , 127]
反码的表示方法是:
正数的反码是其本身
负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
[+1] = [0000 0001]原 = [0000 0001]反
[-1] = [1000 0001]原 = [1111 1110]反
补码的表示方法是:
正数的补码就是其本身
负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
[+1] = [0000 0001]原 = [0000 0001]反 = [0000 0001]补
[-1] = [1000 0001]原 = [1111 1110]反 = [1111 1111]补
当数值左、右移时,先将数值转化为其补码形式,移完后,再转换成对应的原码
左移:高位丢弃,低位补零
[+1] = [00000001]补
[0000 0001]补 << 1 = [0000 0010]补 = [0000 0010]原 = [+2]
[-1] = [1000 0001]原 = [1111 1111]补
[1111 1111]补 << 1 = [1111 1110]补 = [1000 0010]原 = [-2]
其中,再次提醒,负数的补码是反码+1;负数的反码是补码-1;
6. 右移
高位保持不变,低位丢弃
[+127] = [0111 1111]原 = [0111 1111]补
[0111 1111]补 >> 1 = [0011 1111]补 = [0011 1111]原 = [+63]
[-127] = [1111 1111]原 = [1000 0001]补
[1000 0001]补 >> 1 = [1100 0000]补 = [1100 0000]原 = [-64]
7. 总结
左移还是右移都先转换成补码形式
左移:高位丢弃,低位补零
右移:低位丢弃,高位不变
8.扩展
1、cout<<(unsigned)(~0)<
上面的输出是怎么样?
第一问:在32位机器上,[~0] = [1111 1111 .... 1111]原
计算机会将[1111 1111 .... 1111]看成补码的形式,即 会输出(unsigned)[1111 1111 .... 1111]补 对应的原码 。
[1111 1111 .... 1111]补 转化成 unsigned 类型 ,高位就不是符号位了,在32位机器,[1111 1111 .... 1111]对应的十进制 。即 2^32 - 1 = 4294967295
第二问:会输出(int)[1111 1111 .... 1111]补 对应的原码 。此时,高位是符号位且是1,表示负,那么
[1111 1111 .... 1111]补 = [1111 1111 .... 1110]反 = [1000 0000 .... 0001]原 = [-1]
3、cout<
这又怎么输出呢?
首先做(~1>>1),再转化成unsigned类型 或者 int类型
第三问:(~1>>1) = ~[0000 0000 .... 0001] >>1 = [1111 1111 .... 1110] >> 1
= [1111 1111 .... 1111]
转unsigned类型,2^32 - 1 =