个人理解,如有错误,可以指出
参考【科普向】谁都能看懂的CRC(循环冗余校验)原理
参考 CRC校验(2):CRC32查表法详解、代码实现和CRC反转
异或运算满足 :
【a^b=b^a,交换律】
【(a^b)^c=a^(b^c),结合律】
【0^a=a】
【a^1=~a,取反操作】
1字节(Byte),值区间[0,255]
对x属于[0,255] :
CRC32(x)有唯一对应的余数
可以先计算对应的 :
256个CRC32(x)值
local const uint32_t crc_table[256] = {
tole(0x00000000L), tole(0x77073096L), tole(0xee0e612cL), tole(0x990951baL),
tole(0x076dc419L), tole(0x706af48fL), tole(0xe963a535L), tole(0x9e6495a3L),
.......省略..........................................................
tole(0xb3667a2eL), tole(0xc4614ab8L), tole(0x5d681b02L), tole(0x2a6f2b94L),
tole(0xb40bbe37L), tole(0xc30c8ea1L), tole(0x5a05df1bL), tole(0x2d02ef8dL)
};
从一个所有位都设置为1的32位校验和(0xffffffff)开始。这有助于在输入字符串为“0”字节时生成一个非零的输出值。
在循环结束后,将计算出的CRC值与0xffffffff进行异或运算(这与对CRC值进行二进制取反操作相同)。【a^1=~a,取反操作,0 xor 1 = 1,1 xor 1 = 0】
/* ========================================================================= */
# if __BYTE_ORDER == __LITTLE_ENDIAN
# define DO_CRC(x) crc = tab[(crc ^ (x)) & 255] ^ (crc >> 8)
# else
# define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
# endif
uint32_t ZEXPORT crc32_no_comp(uint32_t crc, const Bytef *buf, uInt len)
{
const uint32_t *tab = crc_table;
const uint32_t *b =(const uint32_t *)buf;
size_t rem_len;
#ifdef DYNAMIC_CRC_TABLE
if (crc_table_empty)
make_crc_table();
#endif
crc = cpu_to_le32(crc);
/* Align it */
if (((long)b) & 3 && len) {
uint8_t *p = (uint8_t *)b;
do {
DO_CRC(*p++);
} while ((--len) && ((long)p)&3);
b = (uint32_t *)p;
}
rem_len = len & 3;
len = len >> 2;
for (--b; len; --len) {
/* load data 32 bits wide, xor data 32 bits wide. */
crc ^= *++b; /* use pre increment for speed */
DO_CRC(0);
DO_CRC(0);
DO_CRC(0);
DO_CRC(0);
}
len = rem_len;
/* And the last few bytes */
if (len) {
uint8_t *p = (uint8_t *)(b + 1) - 1;
do {
DO_CRC(*++p); /* use pre increment for speed */
} while (--len);
}
return le32_to_cpu(crc);
}
#undef DO_CRC
uint32_t ZEXPORT crc32 (uint32_t crc, const Bytef *p, uInt len)
{
return crc32_no_comp(crc ^ 0xffffffffL, p, len) ^ 0xffffffffL;
}