【发布时间】:2023-03-13 16:35:01
【问题描述】:
我一直在努力解决这个问题,我正在尝试计算一个字节 [] 的校验和,作为数组中 16 位字的 1s 补码和的 1s 补码。总和相当容易(尽管我确信我可以更有效率)但是当我翻转位并获得“负”值时,它的符号扩展到 4 个字节。按位执行并使用 0xff 给了我正确的值,但是因为我试图将校验和包含在另一个字节数组中,所以我需要它作为一个字节。转换回一个字节再次给了我 4 字节 int 。奇怪的是,我可以将这个(4 字节)值存储在一个字节数组中并打印它而不会引起问题。有什么办法可以强制 Java 只留下一个带负号位的单字节?在此特定示例中,字节为 0xef 和 0xfd。
我计算校验和的代码是:
public byte[] checksum (byte[] b) {
byte[] check = new byte[3] ;
check[1] += b[0];
check[2] += b[1];
check[1] += b[2];
check[2] += b[3];
check[1] += b[4];
check[2] += b[5];
check[1] += b[6];
check[2] += b[7];
check[1] += b[8];
check[2] += b[9];
check[1] += b[10];
check[2] += b[11];
check[1] += b[12];
check[2] += b[13];
check[1] += b[14];
check[2] += b[15];
check[1] += b[16];
check[2] += b[17];
check[1] += b[18];
check[2] += b[19];
check[2] += check[0] ;
byte[] ret = new byte[2] ;
ret[0] = (byte)~check[1];
ret[1] = (byte)~check[2];
return ret ;
}
再次明确,这给了我一个大小为 2 的 byte[],其中每个元素似乎是 4 个字节。
打印返回的数组
byte[] r = checksum (b);
for (int i = 0; i < r.length; ++ i) {
System.out.println (String.format("0x%2s", Integer.toHexString(r[i])).replace(' ', '0')) ;
}
显示
0xffffffef
0xfffffffd
这怎么可能,我该如何避免呢?如果这只是一个显示问题,那很好,但看起来我返回的数组的每个元素实际上都是 4 个字节。
【问题讨论】:
-
“再次明确,这给了我一个大小为 2 的 byte[],其中每个元素是 4 个字节。” 不,它没有。这是
byte[2]。无论您看到的输出表明它是什么,都在误导您。 :-) -
转换回一个字节再次给我 4 字节 int。 这没有意义。请解释你是如何得出这个结论的。
-
如果您从未为
check[0]赋值(所以它是0),那么check[2] += check[0] ;的意义何在?确实,为什么是checkbyte[3],而不是byte[2]? -
大部分问题只是当你从 byte 转到 int 时,如果你希望它被视为无符号,你必须这样做
& 0xFF