CRC原理
// TODO
算法实现
直接计算法
// TODO
查表法
/**
* crc: aaaaaaaa bbbbbbbb cccccccc 01010101
* poly: 11101101 10111000 10000011 00100000
*
* 0
* >>1: 0aaaaaaa abbbbbbb bccccccc c0101010
* poly: 11101101 10111000 10000011 00100000
* xor: 1aaaaaaa abbbbbbb bccccccc c0001010
*
* 1
* >>1: 01aaaaaa aabbbbbb bbcccccc cc010101
*
* 2
* >>1: 001aaaaa aaabbbbb bbbccccc ccc01010
* poly: 11101101 10111000 10000011 00100000
* xor: 110aaaaa aaabbbbb bbbccccc ccc01010
*
* 3
* >>1: 0110aaaa aaaabbbb bbbbcccc cccc0101
*
* 4
* >>1: 00110aaa aaaaabbb bbbbbccc ccccc010
* poly: 11101101 10111000 10000011 00100000
* xor: 11011aaa aaaaabbb bbbbbccc ccccc010
*
* 5
* >>1: 011011aa aaaaaabb bbbbbbcc cccccc01
*
* 6
* >>1: 0011011a aaaaaaab bbbbbbbc ccccccc0
* poly: 11101101 10111000 10000011 00100000
* xor: 1101101a aaaaaaab bbbbbbbc ccccccc0
*
* 7
* >>1: 01101101 aaaaaaaa bbbbbbbb cccccccc
*
* 对于 01010101 来讲, crc这八次计算的过过程是固定了的
* (crc >> 8) ^ table(01010101) = crc'
* 我们可以先计算出这个table值, 再进行计算, 既可加快运算
* 根据 (crc >> 8) ^ table(01010101) = crc'
* 如果 (crc >> 8) = 0 则有 table(01010101) = crc'
* 因此先采用普通方法计算出(0x00 0x00 0x00 01010101)的crc', 也既是table(01010101)
*/
// TODO
完整代码
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
uint32_t *get_crc32_table()
{
static uint32_t static_table[256] = {};
static uint32_t static_table_init = 0;
const uint32_t poly /* reversed */ = 0xedb88320;
uint32_t init = 0;
uint32_t crc = 0;
if (!static_table_init)
{
for (size_t i = 0; i < 256; i++)
{
crc = init ^ i;
for (int j = 0; j < 8; ++j)
{
crc = (crc >> 1) ^ (poly & (-(crc & 1)));
}
static_table[i] = crc;
}
static_table_init = 1;
}
return static_table;
}
uint32_t crc32(uint8_t *data, size_t length)
{
const uint32_t init = 0xffffffff;
const uint32_t xorout = 0xffffffff;
const uint32_t poly /* reversed */ = 0xedb88320;
uint32_t crc = init;
uint32_t *table = NULL;
table = get_crc32_table();
for (int i = 0; i < length; ++i) //用++i以提高效率
{
crc = crc ^ data[i];
// 1. 最符合阅读逻辑的实现
// for (int j = 0; j < 8; ++j)
// {
// if (crc & 1) // LSM为1
// crc = (crc >> 1) ^ poly; //采取反向校验
// else // 0xEDB88320就是CRC-32多项表达式的reversed值
// crc = crc >> 1;
// }
// 2. 去掉1的判断逻辑, 完全靠运算
// for (int j = 0; j < 8; ++j)
// {
// crc = (crc >> 1) ^ (poly & (-(crc & 1)));
// }
// 3. 查表法
crc = (crc >> 8) ^ table[crc & 0xff];
}
return crc ^ xorout;
}
int main(int argc, char const *argv[])
{
uint8_t data[] = {0x11, 0x22};
size_t length = sizeof(data);
uint32_t crc = 0;
crc = crc32(data, length);
assert(crc == 0xC760700B);
return 0;
}