function dataGet(byte:Byte):Number{
return byte&0xFF;
}
为什么要做&0xFF的位运算?
先看 源码 反码 补码,计算机内部存储的二进制码是补码。原码最高位位符号位,0表示正数,1表示负数,除非变量特别声明为unsigned类型则最高位就非符号而表示的是值(这个在JAVA/js里没有),计算机存储器和编译器之间具体怎么去转化unsigned这里不讨论,如果讨论就扯远了。一般我们讨论的都是带符号的二进制码,计算机内部存储也是带符号,只要带符号,低字节转为高字节,全部补1,切记!
十进制数 | 原码 | 反码 | 补码 |
---|---|---|---|
85 | 0101 0101 |
0101 0101 |
0101 0101 |
-85 | 1101 0101 |
1010 1010 |
1010 1011 |
9 | 0000 1001 |
0000 1001 |
0000 1001 |
-9 | 1000 1001 |
1111 0110 |
1111 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,而如果是负数,就必须要弄清楚当前编译器是原码还是补码做位运算了,原码运算不变,补码运算会变。