为何与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.
相关推荐
例如,如果你想把一个字节的低8位清零,可以将其与0xFF进行按位与,因为0xFF的高8位为0,这样就会清除掉原有值的高8位。 2. **提取位字段**:如果知道某个数据的哪几位代表特定的信息,可以通过与特定的位掩码(如0...
加法是将两个数值相加,而异或则是一种位操作,比较两个位,如果相同则结果为0,不同则结果为1。在二进制领域,这两个操作经常被用于数据的组合和变换。 在WinHex中,你可以通过编写脚本来自动化执行这些操作。脚本...
标题"ignore_0xff.rar_scale"暗示了我们正在处理一个与忽略特定字节(在这种情况下是0xff)相关的压缩文件,可能涉及到某种特定的编码或解码算法优化。描述中的"sf_estim.h"表明文件包含了关于“scale factor ...
4. **翻转特定的位**:通过与一个掩码进行“按位异或”运算,可以将特定的位从1翻转为0,或者从0翻转为1。例如,通过与一个掩码进行异或运算,可以翻转a的所有奇数位。 位运算的深入理解和灵活运用,对于提高程序...
- **置位**:如果要将一个数据的第n位置为1,可以先将该位置为0,其他位置为1的掩码与原数进行或运算。例如,将a的第10位置为1,可以使用一个掩码0x100,然后进行a|0x100运算。 位运算在C语言中提供了直接操作内存...
逻辑与运算(AND)是数字电路中最基本的逻辑操作之一,它将两个二进制位进行比较,只有当两个位都为1时,结果才为1,否则为0。在C语言中,我们通常使用`&`运算符来进行逻辑与操作。例如: ```c int a = 0b11001111;...
按位与操作将两个数的每一位进行AND运算,只有两个操作数对应位都为1时结果位才为1,否则为0。在给定文档中,`bitAnd`函数使用摩根定律来实现按位与操作,通过利用按位取反(NOT)和按位或(OR)来达到目的。 ```c ...
最后,通过位运算判断一个整数是否为偶数非常简单,只需要检查其最低位是否为0。例如,`isEven = (i % 2) == 0;`可以简化为`isEven = (i & 1) == 0;`,这种方法同样快600%。 总的来说,位运算在AS3.0中提供了高效且...
1. **byte转int**:将一个byte转换为int,可以通过与0xFF进行按位与操作(AND),然后根据位移规则进行左移或右移操作。例如,`byte b = 10; int i = b & 0xFF;` 这里`b & 0xFF`操作的目的是保证只有低8位参与运算,...
这项设计基于AT89S52单片机,并使用C语言进行编程,旨在帮助学习者掌握单片机基本操作、C语言在硬件控制上的应用以及自增运算在循环中的作用。 AT89S52是一款广泛应用的8位微控制器,由美国Atmel公司生产。它拥有32...
- **高低位交换**: 利用异或运算,可以实现两个数的高低位的交换,如`a = (a & 0xFF00) | ((a & 0xFF) );`。 - **二进制逆序**: 可以通过一系列位移和异或操作将二进制数逆序,如`a = ((a >> 1) & 0x55555555) | ...
首先,我们需要理解C语言中的自增运算符,以及微控制器(如51单片机)的P0端口如何与外部硬件进行交互。 自增运算符是C语言中的一种基本操作符,它有两种形式:前缀自增(++x)和后缀自增(x++)。两者都会使变量x的...
P0_DDR = 0xFF; // 设置P0口为输出模式 while(1) { // 无限循环 P0 = 0x01 ; // 将LED对应位置设为高电平 delay(time); // 控制LED点亮的时间 led_counter++; // 自增计数器 if (led_counter == 8) { // 如果...
int exponent = 150 - ((ival >> 23) & 0xff); if (exponent < 0) ival = (mantissa ); else ival = (mantissa >> exponent); if ((*(int *)&fval) & 0x80000000) ival = -ival; } ``` 这个函数有一个 BUG,...
比如要取反第一个位(最低位),可以将0xFF(二进制全1)与0x01(最低位为1)进行异或操作,因为异或操作具有相同为0,相异为1的特性,所以结果会是0xFE,即第一个位被取反。 3. 乘法化简:乘法操作可以通过位移来...
例如,14(00000000 00001110)与23(00000000 00010111)进行按位与运算得到6(00000000 00000110);-12(11111111 11110100)与6进行按位与运算得到4(00000000 00000100)。 2. 按位或运算符(|):两个相应位...
标题中的“用P1、P0口显示除法运算结果”指的是在微控制器或嵌入式系统中,利用P1和P0端口来显示除法运算的结果。在嵌入式系统开发中,P1和P0口通常作为GPIO(General-Purpose Input/Output)引脚使用,可以设置为...
在易语言中进行RGB与ARGB的转换,需要理解这两种颜色模型的结构,并能正确处理Alpha值。以下是一段简单的易语言源码示例,展示了如何进行转换: ```易语言 .定义 整数型, RGBRed, RGBGreen, RGBBlue, ARGBAlpha, ...
1. **提取高8位**:可以使用位掩码(bit mask)`0xFF00`(在十六进制中,`F`代表1,`0`代表0)并进行按位与(&)运算。例如,`0x1234 & 0xFF00 = 0x1200`。 2. **提取低8位**:使用位掩码`0x00FF`,同样进行按位与...
在TI C5000 DSP系列中使用16比特为最小的储存单位,所以我们就用16比特的整数来进行定点小数运算。16比特的储存单位最多可以表示0x0000到0xffff,65536种状态,如果它表示C语言中的无符号整数的话,就是从0到65535。...