`

为何与0xff进行与运算(转)

 
阅读更多

为何与0xff进行与运算

在剖析该问题前请看如下代码

public static String bytes2HexString(byte[] b) {

  String ret = "";

  for (int i = 0; i < b.length; i++) {

   String hex = Integer.toHexString(b[ i ] & 0xFF);

   if (hex.length() == 1) {

    hex = '0' + hex;

   }

   ret += hex.toUpperCase();

  }

  使用以下的语句,就可以区分使用&0xff和不使用的区别了

  System.out.println(Integer.toBinaryString(b & 0xff)); 输出结果:000000000000000000000000 11010110

  System.out.println(Integer.toBinaryString(b)); 输出结果:       111111111111111111111111 11010110

  return ret;

}

代码解析:

注意这里b[ i ] & 0xFF将一个byte和 0xFF进行了与运算。

b[ i ] & 0xFF运算后得出的仍然是个int,那么为何要和 0xFF进行与运算呢?直接 Integer.toHexString(b[ i ]);

将byte强转为int不行吗?答案是不行的.

其原因在于:

1.byte的大小为8bits而int的大小为32bits

2.java的二进制采用的是补码形式

byte是一个字节保存的,有8个位,即8个0、1。

8位的第一个位是符号位,

也就是说0000 0001代表的是数字1

1000 0000代表的就是-1

所以正数最大位0111 1111,也就是数字127

负数最大为1111 1111,也就是数字-128

上面说的是二进制原码,但是在java中采用的是补码的形式,下面介绍下什么是补码

1、反码:

一个数如果是正,则它的反码与原码相同;

    一个数如果是负,则符号位为1,其余各位是对原码取反;

举个例子:2 二进制吗为 00000010,因为是正数,所以其反码也是 00000010

如果是-2那么,就要把最高位变为1,其他7位按照其正数的位置取反。

2、补码:利用溢出,我们可以将减法变成加法:

对于十进制数,从9得到5可用减法:

    9-4=5    因为4+6=10,我们可以将6作为4的补数

    改写为加法:

    +6=15(去掉高位1,也就是减10)得到5.

    对于十六进制数,从c到5可用减法:

    c-7=5    因为7+9=16 将9作为7的补数

    改写为加法:

    c+9=15(去掉高位1,也就是减16)得到5.

在计算机中,如果我们用1个字节表示一个数,一个字节有8位,超过8位就进1,在内存中情况为(100000000),进位1被丢弃。

⑴一个数为正,则它的原码、反码、补码相同

⑵一个数为负,刚符号位为1,其余各位是对原码取反,然后整个数加1

- 1的原码为                10000001

- 1的反码为                11111110

                                                   + 1

- 1的补码为                11111111

0的原码为                  00000000

0的反码为                  11111111(正零和负零的反码相同)

                                          +1

0的补码为                  100000000(舍掉打头的1,正零和负零的补码相同)

Integer.toHexString的参数是int,如果不进行&0xff,那么当一个byte会转换成int时,由于int是32位,

而byte只有8位这时会进行补位,例如补码11111111的十进制数为-1

转换为int时变为11111111 11111111 11111111 11111111好多1啊,呵呵!

即0xffffffff但是这个数是不对的,这种补位就会造成误差。

和0xff相与后,高24比特就会被清0了,结果就对了。

Java中的一个byte,其范围是-128~127的,而Integer.toHexString的参数本来是int,如果不进行&0xff,

那么当一个byte会转换成int时,对于负数,会做位扩展,举例来说,一个byte的-1(即0xff),

会被转换成int的-1(即0xffffffff),那么转化出的结果就不是我们想要的了。

而0xff默认是整形,所以,一个byte跟0xff相与会先将那个byte转化成整形运算,这样,

结果中的高的24个比特就总会被清0,于是结果总是我们想要的。

0xFF (十进制1)

二进制码:00000000 00000000 00000000 11111111

与 0xff 做 & 运算会将 byte 值变成 int 类型的值,也将 -128~0 间的负值都转成正值了。

char c = (char)-1 & 0xFF;

char d = (char)-1;

System.out.println((int)c); 255

System.out.println((int)d); 65535

java中的數值是int,所以0xFF是int,而byte是有符號數,int亦然,直接由byte升為int,符號自動擴展,

而進行了& 0xFF後,就把符號問題忽略掉了,將byte以純0/1地引用其內容,所以要0xFF,不是多餘的,

你用一些Stream讀取文件的byte就知道了,我昨天搞了一天,就不明白為什麼讀出來的數某些byte會

在移位後錯誤的,就是因為這個原因.

把number转换为二进制,只取最低的8位(bit)。因为0xff二进制就是1111 1111

& 运算是,如果对应的两个bit都是1,则那个bit结果为1,否则为0.

比如 1010 & 1101 = 1000 (二进制)

由于0xff最低的8位是1,因此number中低8位中的&之后,如果原来是1,结果还是1,原来是0,结果位还

是0.高于8位的,0xff都是0,所以无论是0还是1,结果都是0.

分享到:
评论

相关推荐

    与上0xFF的意义.zip

    例如,如果你想把一个字节的低8位清零,可以将其与0xFF进行按位与,因为0xFF的高8位为0,这样就会清除掉原有值的高8位。 2. **提取位字段**:如果知道某个数据的哪几位代表特定的信息,可以通过与特定的位掩码(如0...

    winhex先add再xor运算脚本

    加法是将两个数值相加,而异或则是一种位操作,比较两个位,如果相同则结果为0,不同则结果为1。在二进制领域,这两个操作经常被用于数据的组合和变换。 在WinHex中,你可以通过编写脚本来自动化执行这些操作。脚本...

    ignore_0xff.rar_scale

    标题"ignore_0xff.rar_scale"暗示了我们正在处理一个与忽略特定字节(在这种情况下是0xff)相关的压缩文件,可能涉及到某种特定的编码或解码算法优化。描述中的"sf_estim.h"表明文件包含了关于“scale factor ...

    C语言位运算

    4. **翻转特定的位**:通过与一个掩码进行“按位异或”运算,可以将特定的位从1翻转为0,或者从0翻转为1。例如,通过与一个掩码进行异或运算,可以翻转a的所有奇数位。 位运算的深入理解和灵活运用,对于提高程序...

    C语言位运算.pdf

    - **置位**:如果要将一个数据的第n位置为1,可以先将该位置为0,其他位置为1的掩码与原数进行或运算。例如,将a的第10位置为1,可以使用一个掩码0x100,然后进行a|0x100运算。 位运算在C语言中提供了直接操作内存...

    单片机C语言实例-用P0口显示逻辑与运算结果.zip

    逻辑与运算(AND)是数字电路中最基本的逻辑操作之一,它将两个二进制位进行比较,只有当两个位都为1时,结果才为1,否则为0。在C语言中,我们通常使用`&`运算符来进行逻辑与操作。例如: ```c int a = 0b11001111;...

    位运算15个完整优秀实例 计算机系统2

    按位与操作将两个数的每一位进行AND运算,只有两个操作数对应位都为1时结果位才为1,否则为0。在给定文档中,`bitAnd`函数使用摩根定律来实现按位与操作,通过利用按位取反(NOT)和按位或(OR)来达到目的。 ```c ...

    基于as3的位运算详解

    最后,通过位运算判断一个整数是否为偶数非常简单,只需要检查其最低位是否为0。例如,`isEven = (i % 2) == 0;`可以简化为`isEven = (i & 1) == 0;`,这种方法同样快600%。 总的来说,位运算在AS3.0中提供了高效且...

    java byte相互转换详解左右位移

    1. **byte转int**:将一个byte转换为int,可以通过与0xFF进行按位与操作(AND),然后根据位移规则进行左移或右移操作。例如,`byte b = 10; int i = b & 0xFF;` 这里`b & 0xFF`操作的目的是保证只有低8位参与运算,...

    单片机课程设计——用自增运算控制P0口8位LED流水花样.zip

    这项设计基于AT89S52单片机,并使用C语言进行编程,旨在帮助学习者掌握单片机基本操作、C语言在硬件控制上的应用以及自增运算在循环中的作用。 AT89S52是一款广泛应用的8位微控制器,由美国Atmel公司生产。它拥有32...

    位运算的妙用

    - **高低位交换**: 利用异或运算,可以实现两个数的高低位的交换,如`a = (a & 0xFF00) | ((a & 0xFF) );`。 - **二进制逆序**: 可以通过一系列位移和异或操作将二进制数逆序,如`a = ((a &gt;&gt; 1) & 0x55555555) | ...

    C语言12:用自增运算控制P0口8位LED流水花样.rar

    首先,我们需要理解C语言中的自增运算符,以及微控制器(如51单片机)的P0端口如何与外部硬件进行交互。 自增运算符是C语言中的一种基本操作符,它有两种形式:前缀自增(++x)和后缀自增(x++)。两者都会使变量x的...

    用自增运算控制P0口8位LED流水花样

    P0_DDR = 0xFF; // 设置P0口为输出模式 while(1) { // 无限循环 P0 = 0x01 ; // 将LED对应位置设为高电平 delay(time); // 控制LED点亮的时间 led_counter++; // 自增计数器 if (led_counter == 8) { // 如果...

    浮点型转换整型的快速方法介绍

    int exponent = 150 - ((ival &gt;&gt; 23) & 0xff); if (exponent &lt; 0) ival = (mantissa ); else ival = (mantissa &gt;&gt; exponent); if ((*(int *)&fval) & 0x80000000) ival = -ival; } ``` 这个函数有一个 BUG,...

    关于位运算的一些技巧

    比如要取反第一个位(最低位),可以将0xFF(二进制全1)与0x01(最低位为1)进行异或操作,因为异或操作具有相同为0,相异为1的特性,所以结果会是0xFE,即第一个位被取反。 3. 乘法化简:乘法操作可以通过位移来...

    副件 位运算PPT学习教案.pptx

    例如,14(00000000 00001110)与23(00000000 00010111)进行按位与运算得到6(00000000 00000110);-12(11111111 11110100)与6进行按位与运算得到4(00000000 00000100)。 2. 按位或运算符(|):两个相应位...

    用P1、P0口显示除法运算结果.zip

    标题中的“用P1、P0口显示除法运算结果”指的是在微控制器或嵌入式系统中,利用P1和P0端口来显示除法运算的结果。在嵌入式系统开发中,P1和P0口通常作为GPIO(General-Purpose Input/Output)引脚使用,可以设置为...

    易语言RGB与ARGB转换源码

    在易语言中进行RGB与ARGB的转换,需要理解这两种颜色模型的结构,并能正确处理Alpha值。以下是一段简单的易语言源码示例,展示了如何进行转换: ```易语言 .定义 整数型, RGBRed, RGBGreen, RGBBlue, ARGBAlpha, ...

    16位数据取高其8位,低8位,高4位,低4位数据,并重新组合

    1. **提取高8位**:可以使用位掩码(bit mask)`0xFF00`(在十六进制中,`F`代表1,`0`代表0)并进行按位与(&)运算。例如,`0x1234 & 0xFF00 = 0x1200`。 2. **提取低8位**:使用位掩码`0x00FF`,同样进行按位与...

    定点DSP做浮点运算

    在TI C5000 DSP系列中使用16比特为最小的储存单位,所以我们就用16比特的整数来进行定点小数运算。16比特的储存单位最多可以表示0x0000到0xffff,65536种状态,如果它表示C语言中的无符号整数的话,就是从0到65535。...

Global site tag (gtag.js) - Google Analytics