CRC32学习

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值