我正在尝试将C CRC32代码转换为java。下面的代码是我提出的。但它似乎有所不同。在C中计算的预期CRC32是13 82 D8 46)但是下面代码的输出是“最终crc是-2084771805,以十六进制ffffffff83bce823”。有人可以告诉我为什么吗?
C代码
uint32 crc32_update(uint32 crc, const uint8_t *data, uint16 data_len)
{
uint16_t tbl_idx;
while (data_len--) {
tbl_idx = crc ^ (*data >> (0 * 4));
crc = crc_table[tbl_idx & 0x0f] ^ (crc >> 4);
tbl_idx = crc ^ (*data >> (1 * 4));
crc = crc_table[tbl_idx & 0x0f] ^ (crc >> 4);
data++;
}
return crc & 0xffffffff;
}
JAVA代码。
public class crc32trial_3 {
static final long crc_table[] = new long[] {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};
public static long crc32_init()
{
return 0xffffffff;
}
private static long crc32_update(long crc, byte[] data, int data_len)
{
int tbl_idx;
for(int i = 0 ; i < data_len ; i ++) {
tbl_idx = (int)crc ^ (data[i] >> (0 * 4));
crc = crc_table[tbl_idx & 0x0f] ^ (crc >> 4);
tbl_idx = (int)crc ^ (data[i] >> (1 * 4));
crc = crc_table[tbl_idx & 0x0f] ^ (crc >> 4);
//data++;
}
return crc & 0xffffffff;
}
public static void main(String args[])
{
long intialcrc = crc32_init();
long crc;
System.out.println("the intail crc = " + intialcrc);
byte[] packets = new byte[]{ 88,0,1,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,1,0,0,0,-1,-1,-1,-1,0,0,-56,-46,-117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-68,118 };
byte[] totalLenght = new byte[]{100,0,0,0};
byte[] totalSettingBlock = new byte[]{2};
crc = crc32_update(intialcrc,totalLenght,4);
crc = crc32_update(crc, totalSettingBlock,1);
int temp = 28 + 72;
crc = crc32_update(crc,packets, temp);
long finalcrc = crc;
System.out.println(" the final crc is " + finalcrc + " in hex " + Long.toHexString(finalcrc));
}
}
答案 0 :(得分:1)
你需要&#34; L&#34;在所有十六进制常量的末尾。然后我得到46d81382
作为结果,这是接近,但是你所说的预期的排列。
答案 1 :(得分:0)
首先,C和Java中的>>
运算符并不完全相同。 &gt;&gt;在Java中只定义了int和long类型,并且它的总是一个带符号的移位,与C相对,如果左手表达式是无符号的,则无符号的移位是无符号的。 Java中的usigned移位运算符是>>>
。因此,在翻译C {#1}}时,在Java中它变为usigned >> n
。
其次,因为&gt;&gt; (和&gt;&gt;&gt;)存在仅用于int和long在Java中,在signed >>> n
这样的表达式中,该字节经过扩展转换为int first ,并且当字节被签名时,它意味着符号扩展到int,而在C字节中是无符号的,这意味着它们的扩展转换也是无符号的。因此,如果要将字节视为无符号,则必须将其显式转换为unsigned int(通常称为字节屏蔽):(byte) >> 4
。
我不知道为什么你选择将CRC和表声明为 long ,其中 int 就足够了。
相应地更改代码会给出:
int usigned = (byte expression) & 0xFF;
运行它会给出:
public class crctrial3 {
static final int crc_table[] = new int[] { 0x00000000, 0x1db71064,
0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158,
0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
public static int crc32_init() {
return 0xffffffff;
}
private static int crc32_update(int crc, byte[] data, int data_len) {
int tbl_idx;
for (int i = 0; i < data_len; i++) {
// proper byte masking and shift semantics
tbl_idx = crc ^ ((data[i] & 0xFF) >>> (0 * 4));
crc = crc_table[tbl_idx & 0x0f] ^ (crc >>> 4);
tbl_idx = (int) crc ^ ((data[i] & 0xFF) >>> (1 * 4));
crc = crc_table[tbl_idx & 0x0f] ^ (crc >>> 4);
// data++;
}
return crc & 0xffffffff;
}
public static void main(String args[]) {
int intialcrc = crc32_init();
int crc;
System.out.println("the intail crc = " + intialcrc);
byte[] packets = new byte[] { 88, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
-1, -1, -1, 1, 0, 0, 0, -1, -1, -1, -1, 0, 0, -56, -46, -117,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, -1, 0, -68, 118 };
byte[] totalLenght = new byte[] { 100, 0, 0, 0 };
byte[] totalSettingBlock = new byte[] { 2 };
crc = crc32_update(intialcrc, totalLenght, 4);
crc = crc32_update(crc, totalSettingBlock, 1);
int temp = 28 + 72;
crc = crc32_update(crc, packets, temp);
int finalcrc = crc;
System.out.println(" the final crc is " + finalcrc + " in hex "
+ Integer.toHexString(finalcrc));
}
}
看起来字节顺序不匹配,而不知道你用来到你的代码的那个代码是无法解决问题所在。由于13 82 D8 46不是简单的字节顺序反转46 D8 13 82我怀疑你原来只是误读或错误输入。