数据的二进制表示与数据类型转换
date: 2019-04-30
数据的二进制表示
以下先以 java 中的 byte 类型为模板将(长度短,代码好写。。。)
byte b1 = (byte) 0b00000000;//0b 表示后面的数据用二进制表示,0 为八进制,0x 为十六进制,十进制不带前缀
byte b2 = (byte) 0b10000000;
byte b3 = (byte) 0b11111111;
System.out.println(b1);
System.out.println(b2);
System.out.println(b3);
//以上的输出结果为 0、-128、-1
为何二进制与数据是这么对应的?个人理解是方便计算机进行运算。试想以下情况:
- 有一个数
x
的值为-128
,我们使x
加一变为-127
,如果-128
的二进制表示为0b11111111
,那么-127
应当为0b11111110
,虽然值+1
,但是二进制表示却是-1
,底层不符合逻辑。所以逻辑一点,表面上既然+1
,那底层最好也+1
,所以-128
用0b10000000
来表示更合理,-127
则相应的为0b10000001
,底层的确比-128
大1
。
以这种方法表示,0b11111111
则表示 -1
,而 -1
加一之后为 0
,二进制加一为 0b100000000
( 8 个 0
),因为 byte 长度为一个字节,即只有 8 bits,溢出的 1
被舍去,剩下为 0b00000000
,正好为 0
,符合 -1 + 1 = 0
。
数据类型转换
上面的东西看完之后,我们进入正题。
之前我正在用 java 来实现通信,期间需要将各种数据与 byte 类型进行转换,而在将 byte 型转成 int 型数据时发现了一件事情。以如下代码为例:
byte b = (byte) 0xff;//即255
System.out.println(b);
System.out.println((int) b);
System.out.println(b & 0xff);
System.out.println((int) (b & 0xff));
System.out.println(b | 0x00);
System.out.println((int) (b | 0x00));
三行输出分别为 -1、-1、255、255、-1、-1
真是一件很令人头疼的事
我们先得出以下结论:
- 是否进行强制类型转换对结果没有影响
- 让 byte 型数据与
0
进行或 (|
) 运算不会使输出结果发生改变(即以 byte 类型输出,值域为-128~127
) - 让 byte 型数据与
0xff
(相对于 8 bits 的数据来说即各位全是1
)进行与 (&
) 运算,会以比 byte 值域更大的域来输出,输出的数据明显超过了 byte 的值域
现在我们来看看下面这种情况:
byte b = (byte) 0xff;
int num = (int) b;
System.out.println(num );
System.out.println(num & 0xff);
System.out.println(num & 0xffff);
System.out.println(num & 0xffffffff);
System.out.println(num | 0x00);
我们提前将 byte 类型转换成了 int 类型,输出结果如下:-1、255、65535、-1、-1
显然,num
的二进制表示为 0b111111111111111111111111
( 32 个 1
)
我们又得出以下结论:
- 将 byte 型转换成 int 型时(可以拓展为短数据类型转换成长数据类型),会保持值不变(负数高位补
1
,正数高位补0
) - 与上面相反,将 int 型转换成 byte 型时(长变短),如果发生溢值,则会舍弃高位,保留低位
以上就是我进行的全部测试
但是这里还有一个问题没有解决,希望有大神能给我一些帮助:
- 为什么
b&0xff
和b\|0x00
的值不一样,理论上两者都不会使值发生变化
至此,我想讲的就讲完了,谢谢大家的阅读。
个人博客:https://wilfredshen.cn/