项目中出现的0xFF这些是什么意思

项目中出现的0xFF这些是什么意思最近在看源码的时候发现项目中总是出现一些十六进制的写法,一直不知道是什么意思。最近查了一些资料,今天在这里记录一下,希望有相同困扰的童鞋一定要静下心来看完整篇文章。二进制与十六进制原码反码补码按位与按位或为什么要与0xFF进行按位与1.二进制与十六进制首先要说说为什么要聊二进制与十

大家好,欢迎来到IT知识分享网。项目中出现的0xFF这些是什么意思

最近在看源码的时候发现项目中总是出现一些十六进制的写法,一直不知道是什么意思。最近查了一些资料,今天在这里记录一下,希望有相同困扰的童鞋一定要静下心来看完整篇文章。

  • 二进制与十六进制
  • 原码 反码 补码 按位与 按位或
  • 为什么要与0xFF进行按位与

1.二进制与十六进制

首先要说说为什么要聊二进制与十六进制,因为我们知道在计算机存储中是使用二进制来保存数据的。比如int,我们知道是用4个字节来存储,也就是32位。所以我们首先来了解一下他们之间有什么关系。

这里我们举个例子用十进制的12来进行说明:

 

转换为二进制和十六进制的都是什么呢?

大家都知道通过求余数的方式进行转换,所以这里就不多赘述过程了:
二进制:00000000 00000000 00000000 00001100
十六进制:0x0C
这里的0x是因为如果是10以内的数字如果正常的写,其实和十进制的没什么区别,那么为了区分十进制和十六进制,在c语言中要求十六进制的数前面必须加0x。

 

二进制和十六进制之间的转换呢?

上面我们通过求余数的方式进行了数的转换,那么如果一个二进制的数想要转换为十六进制的数呢?除了先转换为十进制再转成十六进制还有别的办法吗?

首先我们来看一个二进制数:1111,它是多少呢?

你可能还要这样计算:1×20+1×21+1×22+1×23=1×1+1×2+1×4+1×8=15

然而,由于1111才4位,所以我们必须直接记住它每一位的权值,并且是从高位往低位记,:8、4、2、1。即,最高位的权值为23=8,然后依次是 22=4,21=2,20=1

记住8421,对于任意一个4位的二进制数,我们都可以很快算出它对应的10进制值,下面列出四位二进制数 xxxx 所有可能的值(中间略过部分)

仅4位的2进制数 快速计算方法 十进制值 十六进制:

1111 = 8 + 4 + 2 + 1 = 15 = F

1110 = 8 + 4 + 2 + 0 = 14 = E

1101 = 8 + 4 + 0 + 1 = 13 = D

1100 = 8 + 4 + 0 + 0 = 12 = C

1011 = 8 + 0 + 2 + 1 = 11 = B

1010 = 8 + 0 + 2 + 0 = 10 = A

1001 = 8 + 0 + 0 + 1 =9 = 9

……

0001 = 0 + 0 + 0 + 1 = 1= 1

0000 = 0 + 0 + 0 + 0 = 0= 0

二进制数要转换为十六进制,就是以4位一段,分别转换为十六进制 :

1111  1101 -> FD

1010 0101 -> A5

1001 1011 -> 9B

反过来,当我们看到 FD时,如何迅速将它转换为二进制数呢?

先转换F:看到F,我们需知道它是15(可能你还不熟悉A~F这五个数),然后15如何用8421凑呢?应该是8 + 4 + 2 + 1,所以四位全为1 :1111

接着转换D : 看到D,知道它是13,13如何用8421凑呢?应该是:8 + 4 + 1,即:1101

所以,FD对应的二进制数就是 1111 1101

由于十六进制转换成二进制相当直接,所以,我们需要将一个十进制数转换成2进制数时,也可以先转换成16进制,然后再转换成2进制,因为十进制是有正负之分的,但是十六进制只能表达无符号的正整数,二进制则是通过另外一种方式表示正负。

 

2.原码 反码 补码 按位与 按位或

大家肯定特别好奇,聊到现在还是没说代码中的那些0x都是干什么的啊。别着急,这些都是在做铺垫,铺垫好了,后面才理解的清楚!

这个标题段的内容大家应该都不陌生,我们知道在计算机中是通过二进制的方式进行存储数据,但是因为一些原因,计算机中是用补码的方式进行存储的,下面再复习一下各个码之间的关系。

对于正数(00000001)原码来说,首位表示符号位,反码 补码都是本身

对于负数(10000001)原码来说,反码是对原码除了符号位之外作取反运算即(111111110),补码是对反码作+1运算即(111111111)

下面我们还是通过一个例子进行说明,这次用-12来举例:

原码 :10000000 00000000 00000000 00001100

反码 :11111111 11111111 11111111 11110011

补码 :11111111 11111111 11111111 11110100

那结合上面的二进制与十六进制的转换,这个补码可以表示成什么呢?答案是:0xFFFFFFF4

这里有一点要记住,负数在运算的时候,就是用补码来参与运算的,所以我们自己在处理位运算的时候,计算要进行转码。

怎么样,是不是稍微有点苗头了,别着急我们再来复习一个位之间的操作。

按位与(&) :两位同时为“1”,结果才为“1”,否则为0 ,例如:3&5 即 0000 0011& 0000 0101 = 00000001 因此,3&5的值得1

按位或(|)  :参加运算的两个对象只要有一个为1,其值为1,例如:3|5 即 00000011 | 0000 0101 = 00000111 因此,3|5的值得7

 

3.为什么要与0xFF进行按位与

首先说说为什么代码中会出现这些十六进制,首先没什么特别的地方,就是计算机在进行转换的时候,十六进制转二进制比我们用十进制转的快。

但是可能我们现在并不需要这点微小的提升。还有一点就是在进行位运算的时候,用十六进制看起来比较直观,仅此而已。

一般出现与0xFF进行位运算的时候,都是int与byte之间有转换,所以这里我们首先创建一个byte的数组,byte[10]

byte1个字节存储,int是4个字节存储,所以计算机在进行byte转int的时候会将高位进行补1操作,举个例子:

比如-127,其计算机存储的补码是10000001(8位)

在将byte转int的时候,jvm作了一个补位的处理,因为int类型是32位所以补位后的补码就是 :11111111 11111111 11111111 10000001(32位),这个32位二进制补码表示的也是-127

发现没有,虽然 byte->int 计算机背后存储的二进制补码由 10000001(8位)转化成了 : 11111111 11111111 11111111  10000001(32位)很显然这两个补码表示的十进制数字依然是相同的。

那么我做byte->int的转化 所有时候都只是为了保持十进制的一致性吗?

不一定吧?好比我们拿到的文件流转成byte数组,难道我们关心的是byte数组的十进制的值是多少吗?我们关心的是其背后二进制存储的补码吧。

所以大家应该能猜到为什么byte类型的数字要&0xFF再赋值给int类型,其本质原因就是想保持二进制补码的一致性。

当byte要转化为int的时候,高的24位必然会补1,这样,其二进制补码其实已经不一致了,&0xFF可以将高的24位置为0,低8位保持原样。这样做的目的就是为了保证二进制数据的一致性。

当然,保证了二进制数据性的同时,如果二进制被当作byte和int来解读,其10进制的值必然是不同的,因为符号位位置已经发生了变化。

像例2中 :

int c = a[0] & 0xFF –> a[0] & 0xFF = 11111111 11111111 11111111 10000001 & 11111111 = 00000000 00000000 00000000 10000001 ,这个值算一下就是129。

有人问为什么上面的式子中a[0]不是8位而是32位,因为当系统检测到byte可能会转化成int或者说byte与int类型进行运算的时候,就会将byte的内存空间高位补1(也就是按符号位补位)扩充到32位,再参与运算。

上面的0xFF其实是int类型的字面量值,所以可以说byte与int进行运算。

 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/32382.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信