byte为什么要与上0xff?

本文深入解析了字节与整型转换过程中补码的原理,解释了为什么在转换前需要对字节进行 & 0xff 操作,确保二进制补码的一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

无意间翻看之间的代码,发现了一段难以理解的代码。

     byte[] bs = digest.digest(origin.getBytes(Charset.forName(charsetName))) ;  
          
        for (int i = 0; i < bs.length; i++) {  
            int c = bs[i] & 0xFF ;
            if(c < 16){ 
                sb.append("0");  
            }  
            sb.append(Integer.toHexString(c)) ;  
        }  
        return sb.toString() ;  

bs是由一段字符串经过MD5加密后,输出的byte数组。我起初难以理解为什么在接下来的循环中要将bs[i]&oxFF再复制给int类型呢?

bs[i]是8位二进制,0xFF转化成8位二进制就是11111111,那么bs[i]&0xFF不是还是bs[i]本身吗?有意思吗?

 

后来我又写了一个demo

package jvmProject;

public class Test {

    public static void main(String[] args) {
        byte[] a = new byte[10];
        a[0]= -127;
        System.out.println(a[0]);
        int c = a[0]&0xff;
        System.out.println(c);
    }
}

我先打印a[0],在打印a[0]&0xff后的值,本来我想结果应该都是-127.

但是结果真的是出人意料啊!

-127

129

到底是为什么呢?&0xff反而不对了。

 

楼主真的是不懂啊,后来往补码那个方向想了想。

记得在学计算机原理的时候,了解到计算机内的存储都是利用二进制的补码进行存储的。

复习一下,原码反码补码这三个概念

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

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

概念就这么简单。

 

当将-127赋值给a[0]时候,a[0]作为一个byte类型,其计算机存储的补码是10000001(8位)。

将a[0] 作为int类型向控制台输出的时候,jvm作了一个补位的处理,因为int类型是32位所以补位后的补码就是1111111111111111111111111 10000001(32位),这个32位二进制补码表示的也是-127.

发现没有,虽然byte->int计算机背后存储的二进制补码由10000001(8位)转化成了1111111111111111111111111 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=1111111111111111111111111 10000001&11111111=000000000000000000000000 10000001 ,这个值算一下就是129,

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

 

转载于:https://www.cnblogs.com/think-in-java/p/5527389.html

&lt;think&gt;好的,我现在需要解释C语言中位操作使用0xFF作为掩码的原因。首先,我得回忆一下0xFF在二进制中的表示。0xFF是十六进制,转换成二进制就是八个1,也就是11111111,占一个字节。在C语言中,一个字节有8位,所以0xFF可以用来屏蔽一个字节的数据。 接下来,用户可能想知道为什么要用这样的掩码。常见的用途包括提取特定的字节或者清除其他位。比如,当处理32位整数时,如果想获取最低的8位,可以用n &amp; 0xFF,这样高位都会被置0,只保留最低的8位。这在处理颜色值、网络字节序或者数据包时很常见。 另外,掩码操作还可以用于位字段的隔离。例如,当处理一个包含多个标志位的变量时,使用不同的掩码可以检查或修改特定的标志。比如,引用中的例子x = ((x &amp; 0xffff0000) &gt;&gt; 16) | ((x &amp; 0x0000ffff) &lt;&lt; 16);,这里用到了0xffff00000x0000ffff来交换高低16位,类似地,0xFF可以用于交换字节。 还需要考虑不同数据类型的位数问题。比如,在32位系统中,uint32_t是32位,而0xFF对应的是8位,所以掩码操作可能用于逐个字节处理。例如,反转位或者计算汉明重量时,可能需要逐字节或逐位检查,这时候掩码就派上用场了。比如引用中的hammingWeight函数,用mask逐位检查是否为1,这里的mask初始为1,然后左移,可能和0xFF的作用类似,但0xFF一次处理更多位。 另外,0xFF在位移操作中也很重要。比如,当右移操作后,高位可能会填充符号位(对于有符号数),这时候用0xFF掩码可以确保只取需要的部分,避免符号扩展的问题。例如,假设有一个有符号字符,右移之后,用0xFF可以确保只保留低8位,而不会受到符号位的影响。 可能还需要提到位操作中的其他常见掩码,比如0xFFFF(16位)、0xFFFFFFFF(32位)等,但用户的问题集中在0xFF上,所以重点解释8位的情况。同时,结合用户提供的引用中的例子,比如reverseBits函数中使用mask=1&lt;&lt;31,然后逐步右移,可能可以对比说明0xFF作为掩码的不同应用场景。 最后,总结使用0xFF的主要原因:隔离特定字节、清除无关位、防止符号扩展、便于进行位操作等。同时,可以举一些具体的例子,比如从32位整数中提取四个字节中的某一个,或者将多个字节组合成一个更大的整数,这时候掩码操作就非常有用。&lt;/think&gt;在C语言中,使用`0xFF`作为位掩码(bitmask)主要用于隔离或操作数据中的特定字节。其核心原理是通过位运算的(`&amp;`)、或(`|`)、移位(`&lt;&lt;`或`&gt;&gt;`)等操作,实现对特定位段的控制。 ### 1. `0xFF`的二进制含义 - `0xFF`是十六进制数,对应二进制`11111111`,即**8个连续的1**,占据一个字节(8位)。 - 例如,在32位整数`uint32_t n`中,`n &amp; 0xFF`会保留最低8位(即第一个字节),其他位清零。 ### 2. 典型应用场景 #### (a) 提取单个字节 ```c uint32_t num = 0x12345678; uint8_t first_byte = num &amp; 0xFF; // 提取最低字节: 0x78 uint8_t second_byte = (num &gt;&gt; 8) &amp; 0xFF; // 提取第二字节: 0x56 ``` 通过右移后`0xFF`掩码结合,可逐字节提取数据[^3]。 #### (b) 防止符号扩展 对有符号数右移时,高位会填充符号位。掩码`0xFF`可清除高位: ```c int8_t a = -5; // 二进制: 11111011 int32_t b = a; // 符号扩展: 0xFFFFFFFB int32_t c = a &amp; 0xFF; // 清除高位: 0x000000FB ``` #### (c) 位字段操作 在协议或硬件寄存器中,常用掩码操作特定位段: ```c // 假设寄存器REG的bit3~bit0表示状态码 uint8_t status = (REG &amp; 0x0F); // 提取低4位 ``` #### (d) 结合移位运算 引用中的`reverseBits`函数通过掩码和移位实现位反转[^1]: ```c uint32_t mask = 1; for(int i = 0; i &lt; 32; ++i) { if(mask &amp; n) ret |= 1; // 检查当前位是否为1 mask &lt;&lt;= 1; // 左移掩码以检查下一位 } ``` ### 3. 为什么选择`0xFF`? - **精确控制范围**:`0xFF`覆盖一个字节,适合处理8位数据(如ASCII字符、颜色通道)。 - **兼容性**:内存对齐(如结构体位域)、网络传输(字节流)等场景直接兼容。 - **高效性**:位操作是底层硬件直接支持的原子操作,速度极快[^2]。 ### 4. 扩展案例 在计算汉明重量(Hamming Weight)时,可通过掩码逐位统计: ```c int hammingWeight(uint32_t n) { int count = 0; while(n) { n &amp;= n - 1; // 每次清除最低位的1 count++; } return count; } ``` 此方法利用`n &amp; (n-1)`快速消除最低有效位的1。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值