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在线计算工具

使用示例:

多项式统计

相关推荐
淘源码d1 小时前
医院专业级PACS系统完整源码(C+VC+MSSQL)
c语言·数据库·sqlserver·源码·pacs系统·医学影像系统
Rain5091 小时前
mini-cc 终端 UI:用 React 写 CLI 是什么体验
前端·人工智能·react.js·ui·架构·前端框架·ai编程
wu8587734571 小时前
向量数据库不是银弹:从枚举漏检到 ReACT 多轮召回的实践路径
前端·数据库·react.js
meilindehuzi_a1 小时前
深入理解 JavaScript 执行机制:从编译阶段到调用栈底层实现
开发语言·javascript·ecmascript
古怪今人1 小时前
[前端]HTML盒模型与尺寸,标准文档流,块级元素、内联元素和行内块,CSS选择器
前端·css
LONGZETECH2 小时前
汽车仿真教学软件技术实现深度解析:从三维建模到学情数据闭环
c语言·3d·unity·架构·汽车
小雨下雨的雨2 小时前
基于鸿蒙PC Electron框架技术完成的表单验证技术详解
前端·javascript·华为·electron·前端框架·鸿蒙
提子拌饭1332 小时前
饮料含糖量查询应用 - 鸿蒙PC用Electron框架完整实现
前端·javascript·华为·electron·前端框架·鸿蒙
JustHappy2 小时前
古法编程秘籍(五):什么是进程和线程?从软件到 CPU 的一次完整旅程
前端·后端·代码规范