将一个 CRC 算法从 C 语言翻译成 Java

3
我有以下代码,我正在尝试将其转换为Java。
WORD ComputeCRC16(BYTE *data, DWORD data_length)
{
   BYTE *ptr;
   BYTEWORD retval;

    /* Initialize the CRC */
    retval.w = 0xFFFF;

   /* Iterate through the data */
   for (ptr=data; ptr<data+data_length; ptr++)
   {
      // retval.w = IterateCRC16(ptr, retval);
      retval.w = retval.b.hi ^ (ccittrev_tbl[retval.b.lo ^ *ptr]);

   }

   /* Finalize the CRC */
   retval.w = ~retval.w;

   /* Done. */
   return retval.w;
}

下面这行代码是什么意思?
retval.w = retval.b.hi ^ (ccittrev_tbl[retval.b.lo ^ *ptr]);

如果我将 retval 转换为 Java,它应该是一个 int 类型,对吗?但是如果这样的话,它怎么可能有名为"w"的成员变量呢?请指导我如何将上述行转换为 Java。

我正在编辑问题以发布我错过的部分。

typedef union
{
  WORD  w;
  struct
  {
     BYTE  lo,
        hi;
   } b;
} BYTEWORD;         

根据建议进行了编辑:

static int calculate_crc(byte[] data) {
     int retval_w = 0x0000;
     int ccittrev_tbl[] = {
                0x0000,  0xC0C1,  0xC181,  0x0140,  0xC301,  0x03C0,  0x0280,  0xC241,
                0xC601,  0x06C0,  0x0780,  0xC741,  0x0500,  0xC5C1,  0xC481,  0x0440,
                0xCC01,  0x0CC0,  0x0D80,  0xCD41,  0x0F00,  0xCFC1,  0xCE81,  0x0E40,
                0x0A00,  0xCAC1,  0xCB81,  0x0B40,  0xC901,  0x09C0,  0x0880,  0xC841,
                0xD801,  0x18C0,  0x1980,  0xD941,  0x1B00,  0xDBC1,  0xDA81,  0x1A40,
                0x1E00,  0xDEC1,  0xDF81,  0x1F40,  0xDD01,  0x1DC0,  0x1C80,  0xDC41,
                0x1400,  0xD4C1,  0xD581,  0x1540,  0xD701,  0x17C0,  0x1680,  0xD641,
                0xD201,  0x12C0,  0x1380,  0xD341,  0x1100,  0xD1C1,  0xD081,  0x1040,
                0xF001,  0x30C0,  0x3180,  0xF141,  0x3300,  0xF3C1,  0xF281,  0x3240,
                0x3600,  0xF6C1,  0xF781,  0x3740,  0xF501,  0x35C0,  0x3480,  0xF441,
                0x3C00,  0xFCC1,  0xFD81,  0x3D40,  0xFF01,  0x3FC0,  0x3E80,  0xFE41,
                0xFA01,  0x3AC0,  0x3B80,  0xFB41,  0x3900,  0xF9C1,  0xF881,  0x3840,
                0x2800,  0xE8C1,  0xE981,  0x2940,  0xEB01,  0x2BC0,  0x2A80,  0xEA41,
                0xEE01,  0x2EC0,  0x2F80,  0xEF41,  0x2D00,  0xEDC1,  0xEC81,  0x2C40,
                0xE401,  0x24C0,  0x2580,  0xE541,  0x2700,  0xE7C1,  0xE681,  0x2640,
                0x2200,  0xE2C1,  0xE381,  0x2340,  0xE101,  0x21C0,  0x2080,  0xE041,
                0xA001,  0x60C0,  0x6180,  0xA141,  0x6300,  0xA3C1,  0xA281,  0x6240,
                0x6600,  0xA6C1,  0xA781,  0x6740,  0xA501,  0x65C0,  0x6480,  0xA441,
                0x6C00,  0xACC1,  0xAD81,  0x6D40,  0xAF01,  0x6FC0,  0x6E80,  0xAE41,
                0xAA01,  0x6AC0,  0x6B80,  0xAB41,  0x6900,  0xA9C1,  0xA881,  0x6840,
                0x7800,  0xB8C1,  0xB981,  0x7940,  0xBB01,  0x7BC0,  0x7A80,  0xBA41,
                0xBE01,  0x7EC0,  0x7F80,  0xBF41,  0x7D00,  0xBDC1,  0xBC81,  0x7C40,
                0xB401,  0x74C0,  0x7580,  0xB541,  0x7700,  0xB7C1,  0xB681,  0x7640,
                0x7200,  0xB2C1,  0xB381,  0x7340,  0xB101,  0x71C0,  0x7080,  0xB041,
                0x5000,  0x90C1,  0x9181,  0x5140,  0x9301,  0x53C0,  0x5280,  0x9241,
                0x9601,  0x56C0,  0x5780,  0x9741,  0x5500,  0x95C1,  0x9481,  0x5440,
                0x9C01,  0x5CC0,  0x5D80,  0x9D41,  0x5F00,  0x9FC1,  0x9E81,  0x5E40,
                0x5A00,  0x9AC1,  0x9B81,  0x5B40,  0x9901,  0x59C0,  0x5880,  0x9841,
                0x8801,  0x48C0,  0x4980,  0x8941,  0x4B00,  0x8BC1,  0x8A81,  0x4A40,
                0x4E00,  0x8EC1,  0x8F81,  0x4F40,  0x8D01,  0x4DC0,  0x4C80,  0x8C41,
                0x4400,  0x84C1,  0x8581,  0x4540,  0x8701,  0x47C0,  0x4680,  0x8641,
                0x8201,  0x42C0,  0x4380,  0x8341,  0x4100,  0x81C1,  0x8081,  0x4040
            };

        for (byte b : data) {
            retval_w = ((retval_w>>8)&0xff) ^ (ccittrev_tbl[(retval_w&0xff) ^ b]);

        }
}

1
那么[C++]标签是用来做什么的? - Arc676
1
这是按位异或运算符 http://en.cppreference.com/w/cpp/language/operator_arithmetic#Bitwise_logic_operators - Denis
Java 甚至有位运算符吗? - Lundin
伙计们,我认为这是一段 C++ 代码而不是 Java 代码。他想把它转换成 Java。 - Humam Helfawi
1
看起来BYTEWORD是某种结构体或联合体。请提供定义BYTEWORD的代码;然后这段代码摘录就会更有意义。 - Marc Khadpe
显示剩余13条评论
2个回答

7

根据代码,我猜测BYTEWORD是一个无符号short和两个字节结构体的联合体,因此作者可以轻松地访问这个short的高低字节,例如:

typedef union BYTEWORD
{
     short w;
     struct {
         char lo, hi;
     } b;
} BYTEWORD;

由于Java不支持union(并且正如在讨论中提到的,上述存在大小端问题),因此您将需要使用>>|&操作符来访问short类型变量的高8位和低8位:
  short retval_w = -1;
  ...
  retval_w = ((retval_w>>8)&0xff) ^ (ccittrev_tbl[(retval_w&0xff) ^ (data[i]&0xff)]);

是的,我也这么认为。0xFFFF 是短整型的一个很好的指示器,而 hi 看起来非常类似于高字节访问。 - Stefan
1
你关于联合体的看法可能是正确的。但是为了记录,编写这样的联合体是不好的实践,因为它们依赖于字节序。相反,使用移位和按位 & 掩码,如此处所示,以获得可移植的代码。当您可以轻松实现可移植性时,从来没有理由编写非可移植性代码。 - Lundin
@Lundin:是的,我完全同意原始代码的(非)质量,虽然我没有看到原始代码,但也许至少有#if LOW_ENDIAN块来处理字节序。 - Zbynek Vyskovsky - kvr000
@ZbynekVyskovsky-kvr000 所以这将是我的代码中唯一的一行,对吗? "retval_w = ((retval_w>>8)&0xff) ^ (ccittrev_tbl[(retval_w&0xff) ^ *ptr]);" - AnOldSoul
@mayooran:是的,正确的。只有一个额外的要点 - 你将不得不用data数组中的当前项替换*ptr,并将其转换为无符号(使用&0xff),请参见更新的答案。 - Zbynek Vyskovsky - kvr000
显示剩余2条评论

0

^ 是一种二元运算符,表示“异或”(XOR)。


我在询问"retval.b.hi"这一行的含义。如果我将retval转换为Java,它应该是一个int类型。那么我该如何编写"retval.b.hi"呢? - AnOldSoul
你的意思是retval是一个int类型,所以它具有int类型的属性? - Humam Helfawi
是的,确实如此!一个整数怎么可能有那样的属性呢? - AnOldSoul
你应该了解什么是.b和.b.h,然后有两个选择:1)创建一个Java类并将这些属性放入其中。2)创建静态方法,可以从int获取'b'和'b.hu'。 - Humam Helfawi
这完全取决于.b和.b.hi是什么。 - Humam Helfawi
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接