右移和与上&0xff作用

(tmp >> 8) & 0xff;

以下是阅读他人文章后,个人对计算 (tmp >> 8) & 0xff; 的理解:

将tmp转为二进制数

6322040->11000000111011101111000,向右移16位(清掉该16位),且左边用0补足16位

00000000000000001100000,将移动后的二进制转10进,等于96

tmp作为byte类型,计算机存储的补码是01100000(8位)

int类型是32位,将tmp作为int传递赋值时需要不为,所以补位后的补码

111111111111111111111111 01100000

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

即使用了&0xff后的补码为 000000000000000000000000 01100000 值等于01100000 等于96

同理:(tmp >> 8) & 0xff;

6322040->11000000111011101111000->00000000110000001110111(十进转二进,向右移走8位,向向补0 八位)

Byte转int 8位转32位,使用0xff将高的24位设为0,低8位保持不变

01110111->11111111111111111111111101110111->000000000000000000000000 01110111=119

tmp & 0xff;( 十进转二进,不移动,使用0xff将高的24位设为0,低8位保持不变)

6322040->11000000111011101111000->00000000000000000000000001111000=120

 文章源自:

byte为什么要与上0xff? - 陈其苗 - 博客园

byte为什么要与上0xff?

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

     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进行运算。

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
16*32点阵数字钟及汉字显示 附:点阵时间显示源程序 //===================================================================================// //*标题:16*32点阵数字钟显示程序 //*说明:时钟信号产生采用DS1302,列采用74HC595驱动(共4个),行驱动采用4-16线译码器74LS154 //*功能:通过动态扫描显示时钟,可显示时,分,秒,日期中的月和日 //*作者:HEY //*日期:2006-05-29 //*邮箱:[email protected] //*备注:此是我刚接触单片机时的一个小制作 程序和电路设计上难免有不足之处 请谅解 //===================================================================================// #include #include #define uchar unsigned char //===================================================================================// //用到的引脚及端口定义 //===================================================================================// sbit SERIALIN_0=P2^0; //定义P2.0为列向第1个74HC595的DATA输入 sbit SERIALIN_1=P2^1; //定义P2.1为列向第2个74HC595的DATA输入 sbit SERIALIN_2=P2^2; //定义P2.2为列向第2个74HC595的DATA输入 sbit SERIALIN_3=P2^3; //定义P2.3为列向第2个74HC595的DATA输入 sbit CLOCK_DATA=P1^0; //定义P1.0为DS1302的DATA端口 sbit CLOCK_RST=P1^1; //定义P1.1为DS1302的复位输出端口 sbit CLOCK_SCLK=P1^2; //定义P1.2为DS1302的时钟信号状态控制 sbit K0=P1^3; //K0为按键1,用来选择要调整时间的选项(时和分) sbit K1=P1^4; //K1为按键2,执行加1 sbit CLOCK=P2^4; //74HC595的移位时钟控制 sbit LATCH=P2^5; //74HC595的锁存输出时钟控制 void control(); //调整时间控制函数 void time(); uchar CLOCK_TIME[3]={0,0,0}; //定义时钟时间数据存储区,分别为(时,分,秒) uchar BUFFER[8]={0,0,0,0,0,0,0,0}; //显示缓冲区 uchar YEAR[3]={0,0,0}; //定义时钟年月日数据存储区 uchar temp[4]={0,0,0,0}; //定义74HC595的移位缓冲区 uchar FLASH_STOP; //显示小时和分钟之间的两点控制位 uchar sec_flash; //用单片机定时器模拟的一秒(用来控制小时和分中之间的两点) //==============================================

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值