为什么在JAVA/JAVASCRIPT里要做&0xFF位运算

function dataGet(byte:Byte):Number{
    return byte&0xFF;
}

为什么要做&0xFF的位运算?

先看 源码  反码  补码,计算机内部存储的二进制码是补码。原码最高位位符号位,0表示正数,1表示负数,除非变量特别声明为unsigned类型则最高位就非符号而表示的是值(这个在JAVA/js里没有),计算机存储器和编译器之间具体怎么去转化unsigned这里不讨论,如果讨论就扯远了。一般我们讨论的都是带符号的二进制码,计算机内部存储也是带符号,只要带符号,低字节转为高字节,全部补1,切记!

  • 原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值。
  • 反码的表示方法是:正数的反码是其本身;负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。
  • 补码的表示方法是:正数的补码就是其本身;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1。 (即在反码的基础上+1)
  • 十进制数原码反码补码
    850101 01010101 01010101 0101
    -851101 01011010 10101010 1011
    90000 10010000 10010000 1001
    -91000 10011111 01101111 0111

    要想将计算机中存储的二进制码也就是补码转换成十进制数,首先得转换成原码,然后再转换成十进制数据。负数的源码转补码和补码转源码是同样的操作,除开符号位以外,其他位取反加1.再强调最高位为符号位。 

         现在来说为什么JAVA/JS里低字节转高字节要做0xFF位运算了.上面提到了unsigned这个关键字,它的意思表示无符号。而一般变量只要没有类似这unsigned特别标注的都是有符号的,那么有符号的变量在低字节转高字节时高位默认全部高位补1

         有了上面的基础,那么就说说为什么要做&0xFF了: 

//以上面9和-9为例子 ,这里Byte暂时表示比特类型一个字节,Number类型暂时代表4个字节
1.  varableByte:Byte = 9; //一个字节存储9
2.  varableNumber:Number = varableByte&0xFF;

//这里为什么不用&0xFF
3.  varableByte:Byte = -9; //一个字节存储9
4.  varableNumber:Number = varableByte;




当varableByte为正数9时,我做了&0xFF,当varableByte为负数-9时我却没做位运算。原因就是低字节转高字节高位补1,

如果编译器是原码做位运算:

9: 原码 00001001    转换成number类型后高位补1: 11111111 11111111 11111111 00001001 (请问这个的十进制值还是9吗) ,那么我赶紧补救做位运算,&0xFF的二进制补码00000000 00000000 00000000 11111111 ,运算后得到:

00000000 00000000 00000000 00001001,这个在Number类型下的二进制补码和源码正是十进制数9,这样就保持了值不变。

-9:原码 10001001    转换成number类型后高位补1: 11111111 11111111 11111111  10001001,这个做&0xFF后,

00000000 00000000 00000000 10001001,还好是-9。但我担心编译器用下面补码做位运算。

如果编译器是补码做位运算:

9: 补码 00001001    转换成number类型后高位补1: 11111111 11111111 11111111 00001001 (请问这个的十进制值还是9吗) ,那么我赶紧补救做位运算,&0xFF的二进制补码00000000 00000000 00000000 11111111 ,运算后得到:

00000000 00000000 00000000 00001001,这个在Number类型下的二进制补码和源码正是十进制数9,这样就保持了值不变。

-9:补码 11110111    转换成number类型后高位补1: 11111111 11111111 11111111  11110111,这个做&0xFF后,00000000 00000000 00000000 11110111,这十进制数还是原来的-9吗,变成正数了,哎相当无语。

 

混乱的问题来了:

   1.0xFF的二进制码为什么前面补的是0?去问你的编译器,貌似常量的16进制数据转换成二进制后前面默认补0,估计也不一定,还是要根据自己编译器去发现,真的是无语!

         2.我们做位运算后,编译器解析的是原码还是补码作运算呢?去问编译器吧。实验两次就是知道了,也许各编译器有差异,也许都是统一标准。还是让人无语!!

结语: 至少知道了为什么要&0xFF了,主要是因为在非unsigned的情况下正数在 低位转高位 值会变,为了避免值发生变化,我们才&0xFF,而如果是负数,就必须要弄清楚当前编译器是原码还是补码做位运算了,原码运算不变,补码运算会变

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值