java字节移位逆运算
我有这个密码
byte[] b = new byte[]{-33,-4,20,30};
System.err.println(Arrays.toString(b));
int x = (b[0] << 24) + (b[1] << 16) + (b[2] << 8) + b[3];
b = new byte[]{(byte)(x >> 24), (byte)(x >> 16), (byte)(x >> 8), (byte)(x)};
System.err.println(Arrays.toString(b));
输出:
[-33, -4, 20, 30]
[-34, -4, 20, 30]
我不明白为什么这些操作不是相反的
# 1 楼答案
请忽略我之前的回答;这是完全错误的
我认为这里的问题是,当你以这种方式组合比特时:
你不是在做你认为你在做的事。特别地,假设
b[1]
是负数(它是负数)。当Java进行位移位时,它总是在移位之前将值提升为int
。这意味着b[1]
在升级时将如下所示:这里,前导1来自整数的有符号二补表示,这使得负数由许多前导零表示。当你把这个数字调高时
如果将这些位添加到
(b[0] << 24)
,它的形式为你没有得到
因为代表中领先的1。要解决这个问题,需要在进行加法之前屏蔽符号位。具体来说,如果你改变
到
然后你就把这些碎片掩盖起来
现在当你把这两个值相加,你得到
如你所愿
因此,构成位的正确表达式是通过在适当的时间在适当的掩码中求和而形成的:
我已经在我的系统上测试过了,它似乎运行得很好
希望这有帮助
# 2 楼答案
你的问题是不想要的符号扩展
具体来说,
b[1]
是-4
,或者0xfc
,它被符号扩展到0xfffffffc
,然后左移到0xfffc0000
。这具有将最高有效字节递减1的效果试试看: