CRC即循环冗余校验码(Cyclic Redundancy Check)。
CRC32算法中,这个生成多项式为:
c(x) = 1 + x + x^2 + x^4 + x^5 + x^7 + x^8 + x^10 + x^11 + x^12 + x^16 + x^22 + x^23 + x^26 + x^32。
其对应的数字就为:11101101101110001000001100100000(x^32在实际计算时隐含给出,因此这里没有包含它
的系数),也就是0xEDB88320(多项式对应的数字可能颠倒,颠倒后得到的是0x04C11DB7,其实也是正确的)。
由此可以看出,CRC值也可以看成我们的数据除以一个生成多项式而得到的余数。
容易理解的是位运算
- // 以4 byte数据为例
- #define POLY 0x04C11DB7L // CRC32生成多项式
- unsigned int CRC32_1(unsigned int data)
- {
- unsigned char p[8];
- memset(p, 0, sizeof(p));
- memcpy(p, &data, 4);
- unsigned int reg = 0, idx = 0;
- for(int i = 0; i < 64; i++)
- {
- idx = i/8;
- int hi = (reg>>31)&0x01; // 取得reg的最高位
- // 把reg左移1bit,并移入新数据到reg0
- reg = (reg<<1)| (p[idx]>>7);
- if(hi) reg = reg^POLY; // hi=1就用reg除以g(x)
- p[idx]<<=1;
- }
- return reg;
- }
位运算速度慢,扩展到字节为单位
// 以4 byte数据为例
#define POLY 0x04C11DB7L // CRC32生成多项式
unsigned int CRC32_2(unsigned int data)
{
unsigned char p[8];
memset(p, 0, sizeof(p));
memcpy(p, &data, 4);
unsigned int reg = 0, sum_poly = 0;
for(int i = 0; i < 8; i++)
{
// 计算步骤1
sum_poly = reg&0xFF000000;
for(int j = 0; j < 8; j++)
{
int hi = sum_poly&0x80000000; // 测试reg最高位
sum_poly <<= 1;
if(hi) sum_poly = sum_poly^POLY;
}
// 计算步骤2
reg = (reg<<8)|p[i];
reg = reg ^ sum_poly;
}
return reg;
}
但实际使用的是一种表驱动的方式,
static void init_crc_table(void)
{
unsigned int c;
unsigned int i, j;
for (i = 0; i < 256; i++) {
c = (unsigned int)i;
for (j = 0; j < 8; j++) {
if (c & 1)
c = 0xedb88320L ^ (c >> 1);
else
c = c >> 1;
}
crc_table[i] = c;
}
}
/*计算buffer的crc校验码*/
static unsigned int crc32(unsigned int crc,unsigned char *buffer, unsigned int size)
{
unsigned int i;
for (i = 0; i < size; i++) {
crc = crc_table[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8);
}
return crc ;
}