CRC校验C语言实现-CRC8、CRC16、CRC16的直接计算法、查表法

文章目录

C语言实现代码如下:
其中包括crc8、crc16、crc32的直接计算法、查表法:

bash 复制代码
#include <stdint.h>
#include <stddef.h>

/* ==================== CRC-8 (MAXIM/DOW) ==================== 
   多项式: x^8 + x^2 + x + 1  -> 0x07 (二进制 0000 0111)
   初始值: 0x00
   结果异或: 0x00
   输入/输出反转: 否
   ========================================================= */
#define CRC8_POLY    0x07
#define CRC8_INIT    0x00
#define CRC8_XOROUT  0x00

/* ==================== CRC-16 (XMODEM / CCITT) ====================
   多项式: x^16 + x^12 + x^5 + 1 -> 0x1021
   初始值: 0x0000
   结果异或: 0x0000
   输入/输出反转: 否 (常用于 XMODEM)
   =============================================================== */
#define CRC16_POLY   0x1021
#define CRC16_INIT   0x0000
#define CRC16_XOROUT 0x0000

/* ==================== CRC-32 (以太网 / ZIP) ====================
   多项式: 0x04C11DB7 (标准以太网多项式)
   初始值: 0xFFFFFFFF
   结果异或: 0xFFFFFFFF
   输入反转: 是 (每字节 bit 顺序反转)
   输出反转: 是 (最终结果 bit 顺序反转)
   ============================================================== */
#define CRC32_POLY   0x04C11DB7UL
#define CRC32_INIT   0xFFFFFFFFUL
#define CRC32_XOROUT 0xFFFFFFFFUL

/* crc-8 直接计算法(按位) */
/* function: 直接计算法 */
uint8_t crc8_direct(const uint8_t *data, size_t len) {
    uint8_t crc = CRC8_INIT;
    for (size_t i = 0; i < len; i++) {
        crc ^= data[i];
        for (int bit = 0; bit < 8; bit++) {
            if (crc & 0x80) {
                crc = (crc << 1) ^ CRC8_POLY;
            } else {
                crc <<= 1;
            }
        }
    }
    return crc ^ CRC8_XOROUT;
}

/* crc-8 查表法 */
/* function: 先预生成 256 项的表 */
uint8_t crc8_table[256];
void crc8_table_init(void) {
    for (int i = 0; i < 256; i++) {
        uint8_t crc = (uint8_t)i;
        for (int bit = 0; bit < 8; bit++) {
            if (crc & 0x80)
                crc = (crc << 1) ^ CRC8_POLY;
            else
                crc <<= 1;
        }
        crc8_table[i] = crc;
    }
}

/* function:查表计算 */
uint8_t crc8_table_calc(const uint8_t *data, size_t len) {
    uint8_t crc = CRC8_INIT;
    for (size_t i = 0; i < len; i++) {
        crc = crc8_table[crc ^ data[i]];
    }
    return crc ^ CRC8_XOROUT;
}

/* crc-16 直接计算法(按位) */
/* function: 直接计算法 */
uint16_t crc16_direct(const uint8_t *data, size_t len) {
    uint16_t crc = CRC16_INIT;
    for (size_t i = 0; i < len; i++) {
        crc ^= (uint16_t)data[i] << 8;   // 数据与高8位异或
        for (int bit = 0; bit < 8; bit++) {
            if (crc & 0x8000) {
                crc = (crc << 1) ^ CRC16_POLY;
            } else {
                crc <<= 1;
            }
        }
    }
    return crc ^ CRC16_XOROUT;
}

/* crc-16 查表法 */
/* function: 先预生成 256 项的表 */
uint16_t crc16_table[256];
void crc16_table_init(void) {
    for (int i = 0; i < 256; i++) {
        uint16_t crc = (uint16_t)i << 8;
        for (int bit = 0; bit < 8; bit++) {
            if (crc & 0x8000)
                crc = (crc << 1) ^ CRC16_POLY;
            else
                crc <<= 1;
        }
        crc16_table[i] = crc;
    }
}

/* function: 查表计算 */
uint16_t crc16_table_calc(const uint8_t *data, size_t len) {
    uint16_t crc = CRC16_INIT;
    for (size_t i = 0; i < len; i++) {
        uint8_t index = (uint8_t)(crc >> 8) ^ data[i];
        crc = (crc << 8) ^ crc16_table[index];
    }
    return crc ^ CRC16_XOROUT;
}

/* crc-32 (标准以太网风格,含位反转) */
/* function: 辅助函数:位反转(用于输入字节和最终结果) */
static uint32_t bit_reverse32(uint32_t x) {
    x = ((x & 0x55555555) << 1) | ((x >> 1) & 0x55555555);
    x = ((x & 0x33333333) << 2) | ((x >> 2) & 0x33333333);
    x = ((x & 0x0F0F0F0F) << 4) | ((x >> 4) & 0x0F0F0F0F);
    x = (x << 24) | ((x & 0xFF00) << 8) | ((x >> 8) & 0xFF00) | (x >> 24);
    return x;
}

static uint8_t bit_reverse8(uint8_t x) {
    x = (uint8_t)((x & 0x55) << 1) | ((x >> 1) & 0x55);
    x = (uint8_t)((x & 0x33) << 2) | ((x >> 2) & 0x33);
    x = (uint8_t)((x & 0x0F) << 4) | ((x >> 4) & 0x0F);
    return x;
}

/* function: 直接计算法(按位,处理反转) */
uint32_t crc32_direct(const uint8_t *data, size_t len) {
    uint32_t crc = CRC32_INIT;
    for (size_t i = 0; i < len; i++) {
        uint8_t byte = bit_reverse8(data[i]);  // 输入字节位反转
        crc ^= (uint32_t)byte << 24;
        for (int bit = 0; bit < 8; bit++) {
            if (crc & 0x80000000UL) {
                crc = (crc << 1) ^ CRC32_POLY;
            } else {
                crc <<= 1;
            }
        }
    }
    crc = bit_reverse32(crc);       // 输出结果位反转
    return crc ^ CRC32_XOROUT;
}

/*查表法(4 字节表,常见实现)*/
/*function: 生成 256 项的表(每个表项已经隐含了位反转)*/
uint32_t crc32_table[256];
void crc32_table_init(void) {
    for (int i = 0; i < 256; i++) {
        uint32_t crc = (uint32_t)i << 24;
        for (int bit = 0; bit < 8; bit++) {
            if (crc & 0x80000000UL)
                crc = (crc << 1) ^ CRC32_POLY;
            else
                crc <<= 1;
        }
        crc32_table[i] = crc;
    }
}

/*function: 查表计算(每字节查表一次,自动处理输入反转)*/
uint32_t crc32_table_calc(const uint8_t *data, size_t len) {
    uint32_t crc = CRC32_INIT;
    for (size_t i = 0; i < len; i++) {
        uint8_t byte = bit_reverse8(data[i]);          // 每字节先反转
        uint8_t index = (uint8_t)(crc >> 24) ^ byte;
        crc = (crc << 8) ^ crc32_table[index];
    }
    crc = bit_reverse32(crc);                          // 输出反转
    return crc ^ CRC32_XOROUT;
}

#include <stdio.h>
#include <string.h>

int main() {
    const char *test = "123456789";
    size_t len = strlen(test);
    uint8_t *data = (uint8_t*)test;

    // 初始化查表
    crc8_table_init();
    crc16_table_init();
    crc32_table_init();

    // CRC-8
    printf("CRC-8 direct: 0x%02X\n", crc8_direct(data, len));
    printf("CRC-8 table:  0x%02X\n", crc8_table_calc(data, len));

    // CRC-16
    printf("CRC-16 direct: 0x%04X\n", crc16_direct(data, len));
    printf("CRC-16 table:  0x%04X\n", crc16_table_calc(data, len));

    // CRC-32
    printf("CRC-32 direct: 0x%08X\n", crc32_direct(data, len));
    printf("CRC-32 table:  0x%08X\n", crc32_table_calc(data, len));

    return 0;
}

运行结果:

bash 复制代码
CRC-8 direct: 0xF4
CRC-8 table:  0xF4
CRC-16 direct: 0x31C3
CRC-16 table:  0x31C3
CRC-32 direct: 0xCBF43926
CRC-32 table:  0xCBF43926

在线工具推荐

工具1:

CRC在线计算工具

使用示例:

工具2:

CRC在线计算工具

使用示例:

多项式统计

相关推荐
爱勇宝5 小时前
大多数人不是在使用 AI 赚钱,而是在帮 AI 公司赚钱
前端·后端·程序员
冬奇Lab6 小时前
每日一个开源项目(第143篇):page-agent - 纯 JS 的网页 GUI Agent,无需截图、无需插件、无需后端
前端·人工智能·agent
To_OC8 小时前
LC 994 腐烂的橘子:人人都说是 BFS 入门题,我却写了三遍才过
javascript·算法·leetcode
IT_陈寒11 小时前
React的这个渲染问题连官方文档都没说清楚
前端·人工智能·后端
追逐时光者12 小时前
别再满网找零散工具了,腾讯 QQ 浏览器这个“帮小忙”工具箱真能省时间
前端·后端
To_OC14 小时前
LC 200 岛屿数量:经典 DFS 入门题,我第一次写居然连方向都搞错了
javascript·算法·leetcode
Asmewill14 小时前
grep&curl命令学习笔记
前端
stringwu14 小时前
Flutter 开发必备:MVI 架构的高效实现指南
前端·flutter
用户21366100357215 小时前
Vue2组件化开发与父子通信
前端·vue.js
Momo__16 小时前
TypeScript satisfies 操作符——比 as 更安全的类型守门员
前端·typescript