• Java byte位移操作 注意事项(转载)


    来自:https://www.cnblogs.com/yongdaimi/p/5899362.html

    ===========================================================

    Java对byte 的 + - * / >> >>> << & | ^ (加,减,乘,除,右移,左移,无符号右移,位与,位或,位异或)操作,均会是首先将byte转化为int, 再行运算。这一事实可能导致多种问题:

     
     
    假设我们想进行如下byte运算: 1111 1000 右移1位,再与0000 0001 或运算,得 0111 1101。
    直觉写程序如下:
    byte b = 0xf8;
    byte b2 =  b >> 1 | 0x01;  
     
    这个写法里有多重错误,现逐个纠正:
    1 编译器报错,int无法直接自动转化为byte 
    为解决此问题,加强制转化。
    byte b = (byte)0xf8;
    byte b2 = (byte)( (b >> 1) | 0x01);  
     
     
    2 输出为 1111 1101 不是我们想要的 0011 1101
    原因是>> 是有符号右移,当符号位为1时,左侧补的是1而非0。
    修改为使用 >>> 无符号右移:
    byte b = (byte)0xf8;
    byte b2 = (byte)( (b >>> 1) | 0x01);  
     
    3 运行后发现输出依然为 1111 1101 
    原因是byte在运算前先转化为int再行位运算,因此分解后的运算步骤如下:
    b 转化为int  1111 1000 转化为      11111111 11111111 11111111 11111000
    无符号右移1位                      01111111 11111111 11111111 11111100
    与 0x01 按位或                  01111111 11111111 11111111 11111101
    强制转化回byte     11111101
    解决方案,在右移运算前先 位与 0xff
    byte b = (byte)0xf8;
    byte b2 = (byte)( ((b & 0xff )>>> 1) | 0x01);  //注意必须加括号,因为 >>> 的优先级高于 &
     
     
    4 运行后发现输出为我们想要的结果  0111 1101。运算步骤分解如下:
    b 转化为int  1111 1000 转化为   11111111 11111111 11111111 11111000
    和0xff 进行 & 操作              00000000 00000000 00000000 11111000
    无符号右移1位   00000000 00000000 00000000 01111100
    与 0x01 按位或  00000000 00000000 00000000 01111101
    强制转化回byte  01111101
     
     
     
    5 关于System.out.println();
    byte b = (byte)0xf8;
    System.out.println(b);   --最终输出为-8
    运算步骤为:
    b 转化为int  1111 1000 转化为   11111111 11111111 11111111 11111000
    取符号位 -                      -1111111 11111111 11111111 11111000
    取返+1(因为是按补码运算)      -0000000 00000000 00000000 00001000
    输出  -8
     
     
     
     
     
    最终结论:
    1 区分使用 >> 和 >>>
    2 在 >> 操作前要首先 & 0xff
    3 注意符号优先级,正确使用括号。
    4 需要强烈注意的一点是 & 的优先级小于 + . 因此 a = b & 0xff + 2000 的结果 可能不是你想要的
     
     
     
     
     
     
    附:
    打印byte,int 每个bit值的函数。
     
    public static void printByte(byte b){
        for(int i = 7; i >=0 ; i --){
            int shiftleft = (b >> i) & 0x01;
            System.out.print(shiftleft);
        }
        System.out.println();
    }
     
    public static void printInt(int b){
        for(int i = 31; i >=0 ; i --){
            int shiftleft = (b >> i) & 0x01;
            System.out.print(shiftleft);
        }
        System.out.println();
    }
  • 相关阅读:
    [CISCN2019 总决赛 Day2 Web1]Easyweb
    [极客大挑战 2019]Upload
    [SUCTF 2019]EasyWeb
    2020/2/1 PHP代码审计之任意文件读取及删除漏洞
    2020/1/31 PHP代码审计之文件包含漏洞
    [Luogu P1120]小木棍&#183;加强版
    学习笔记·堆优化$mathscr{dijkstra}$
    [LuoguP1462]通往奥格瑞玛的道路($SPFA+$二分)
    [USACO08JAN]电话线$Telephone Lines$(图论$+SPFA+$ 二分答案)
    [USACO06NOV]玉米田$Corn Fields$ (状压$DP$)
  • 原文地址:https://www.cnblogs.com/del88/p/15839510.html
Copyright © 2020-2023  润新知