我在Objective-C中有这个代码,我想用Java编写它。然而,有(-(crc & 1))
声明给我带来了问题。在一些googeling之后,似乎无条件的否定通常没有明确定义。我虽然不太明白。也许知道CRC的人可以告诉我Java中的等价物是什么。
我需要一个等效的方法作为一个设备,这个Objective-C代码检查我的计算的crc与其自我计算。
+ (UInt32) crc32:(UInt32) crc ofByte: (UInt8) byte
{
int8_t i;
crc = crc ^ byte;
for (i = 7; i >= 0; i--)
{
crc = (crc >> 1) ^ (0xedb88320ul & (-(crc & 1)));
}
return(crc);
}
在评论的帮助下解决了代码。好像我在错误的地方搜索了这个错误。
private void addByteToCRC(byte oneByte) {
crc ^= oneByte & 0xFF;
for (int i = 7; i >= 0; i--)
{
crc = (crc >>> 1) ^ (0xedb88320 & (-(crc & 1)));
}
}
两个校验和都以crc值0xFFFFFFFF开始。
答案 0 :(得分:1)
(Objective-)C和Java之间存在一些差异,但您可能已经发现了错误的问题。 Java没有无符号整数类型。但是它确实有按位运算符,它将整数视为只是位串,而后来的Java版本确实有无符号运算符,当应用于整数时,它们对基础位模式进行操作,就像它们表示无符号值一样。 / p>
表达式crc & 1
将产生0
或1
的结果,具体取决于crc
是偶数还是奇数。
表达式-(crc & 1)
因此评估为0
或-1
。 0
的位模式全为零,-1
的位模式全部为1 - 后者在(目标 - )C中为真,无论整数的基础表示为1或2&# 39;补充,请参阅Is it safe to use -1 to set all bits to true?以获得解释。
表达式0xedb88320ul & (-(crc & 1))
因此评估为0
或0xedb88320
。
表达式crc >> 1
是逻辑或无符号,在(Objective-)C中右移,因为src
被定义为 unsigned (签名整数的右移是"实现定义"在(Objective-)C中)。
任何x ^ 0
的表达式x
评估为x
。
将所有内容放在一起,整个表达式(crc >> 1) ^ (0xedb88320ul & (-(crc & 1)))
有条件地xors crc >> 1
与0xedb88320
基数不同,crc
是奇数还是偶数。
现在您只需要在Java中重现相同的行为。
Java为int
(JLS: Primitive Types and Values)使用32位2的补码整数,并提供按位运算符,将它们视为位串。
十六进制常量仅为0xedb88320
且具有int
(32位)类型。
表达式-(crc & 1)
因此评估为(目标 - )C。
然而,表达式crc >> 1
将不评估与(Objective-)C中的相同。在Java中,>>
是算术右移,它在移位期间复制符号位。这个选择源于使用签名类型的Java。幸运的是,Java还提供>>>
运算符来执行逻辑或无符号,右移。
所以我猜您可能在转换中发现了错误的问题,并且您需要使用>>>
运算符。
HTH
答案 1 :(得分:1)
-(crc & 1)
工作正常,不是你的问题。它的作用是将crc
的低位复制到所有位,因为在二进制补码表示中,-1都是1。
您需要为Java修复两件事,它没有无符号整数。首先,正确的转变需要是一个合乎逻辑的右移>>>
。这避免了在向下移位时复制符号位,而是在零位移位。其次,您需要防止签名扩展到int
的字符,因此byte
(需要在Java中使用不同的名称)需要使用0xff
。所以:
crc ^= octet & 0xff;
和
crc = (crc >>> 1) ^ (0xedb88320ul & (-(crc & 1)));