需要CRC编程帮助,CRC32从.NET类转换为C语言

时间:2012-07-30 15:44:23

标签: c# .net c crc crc32

代码(用C编写):

unsigned long chksum_crc32 (unsigned char *block, unsigned int length)
{
   register unsigned long crc;
   unsigned long i;

   crc = 0xFFFFFFFF;
   for (i = 0; i < length; i++)
   {
      crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *block++) & 0xFF];
   }
   return (crc ^ 0xFFFFFFFF);
}


/* chksum_crc32gentab() --      to a global crc_tab[256], this one will
 *              calculate the crcTable for crc32-checksums.
 *              it is generated to the polynom [..]
 */

void chksum_crc32gentab ()
{
   unsigned long crc, poly;
   int i, j;

   poly = 0xEDB88320L;
   for (i = 0; i < 256; i++)
   {
      crc = i;
      for (j = 8; j > 0; j--)
      {
         if (crc & 1)
         {
            crc = (crc >> 1) ^ poly;
         }
         else
         {
            crc >>= 1;
         }
      }
      crc_tab[i] = crc;
   }
}

首先;我知道CRC的工作原理,首先用指定的多项式计算除数,然后将这个FCS(帧校验序列)附加到数据集并发送给最终用户系统。传输完成后,使用用于计算FCS的相同多项式检查FCS,如果带有该除数的其余数据为零,则表示数据正确。

我不明白这两个功能的实现。根据我的学习,函数chksum_crc32gentab()生成校验和可以采用32位CRC多项式的所有可能的十六进制值。我得到的一件事是 poly = 0xEDB88320L; 与多项式是否相等。我也不了解这个函数底部的逻辑。例如,条件 if(crc&amp; 1),这是否意味着对于crc中的每个位为1,计算,否则向右移一位?

我也不明白 chksum_crc32(unsigned char * block,unsigned int length); 。这个函数只接受一个字节串并将它们转换为用表计算的正确crc值吗?我想我对for循环中使用的逻辑感到困惑。

如果有人理解这段代码,解释会很棒;这对于.net类的crc32转换是有效的,这是一个如何转换数据然后被这些函数使用的例子: (C#来源)

      MemoryStream ms = new MemoryStream(System.Text.Encoding.Default.GetBytes(input));

            foreach (byte b in crc32.ComputeHash(ms))
                hash += b.ToString("x2").ToLower();

以下是C代码的原始网站和项目。的 http://www.codeproject.com/Articles/35134/How-to-calculate-CRC-in-C

任何解释都会有所帮助

2 个答案:

答案 0 :(得分:3)

或者只是google it ...第二次点击是:http://www.opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/libkern/crc32.c

从C#的 hard 方式向后移植它,大多数算法已经在C中。

答案 1 :(得分:3)

在CRC计算中,二元多项式(x^n与0或1系数之和)简单地表示为二进制字,其中0或1的位置表示x的幂它是一个系数。

0xEDB88320L将CRC32多项式的系数表示为1,其中有x^n项(除了x^32项,省略)。 CRC32多项式(为什么哦为什么不stackoverflow有像Math.stackexchange这样的TeX方程式 - 我不能在这里写出不错的方程式!叹气,对不起咆哮... )是:

x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1

由于在比特排序方面如何定义CRC,因此最低系数位于最高位。因此,上面的十六进制常量中的第一个E1110表示(按位从左到右的顺序),1 + x + x^2

您可以在crc32.c的{​​{1}}源文件中找到构造,其中显示了一个代码段:

static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};

    /* make exclusive-or pattern from polynomial (0xedb88320UL) */
    poly = 0;
    for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
        poly |= (z_crc_t)1 << (31 - p[n]);

    /* generate a crc for every 8-bit value */
    for (n = 0; n < 256; n++) {
        c = (z_crc_t)n;
        for (k = 0; k < 8; k++)
            c = c & 1 ? poly ^ (c >> 1) : c >> 1;
        crc_table[0][n] = c;
    }

上面的if (crc & 1)c & 1 ?会在转移之前的每一步查看CRC的低位。这实际上是多项式减法运算的进位,因此如果它是1,则从CRC中的向下移位的多项式中减去(排除)多项式(乘以x)。无论低位是否为1,CRC都会向下移位。

您显示的chksum_crc32()函数确实计算了所提供数据块的CRC。它是用于对字节串进行CRC计算的标准基于表的方法,它通过CRC的异或数据字节和低字节对表进行索引。这与一次移位一位并将多项式应用于1位完全相同,但是在一步而不是八步中执行。 CRC有效地乘以x^8>> 8),并且取决于索引值,在各种移位位置处使用多项式0到8次的异或效果进行排他。它只是使用预先计算的表格的速度技巧。

您可以在zlib的crc32.c中找到更多极端速度技巧,它使用更大的表并一次处理更多数据。