代码(用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
任何解释都会有所帮助
答案 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,因此最低系数位于最高位。因此,上面的十六进制常量中的第一个E
是1110
表示(按位从左到右的顺序),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
中找到更多极端速度技巧,它使用更大的表并一次处理更多数据。