当前位置: 首页 > news >正文

深入理解CRC32:参数详解与C语言实现(附完整源码及验证)

摘要

本文详细介绍 CRC32 校验算法的各项参数(widthpolyinitRefInRefOutXorOut),并给出可以直接在项目中使用的 C 语言源码。代码采用直接按位计算的方式,完全符合“输入输出均反射”的 CRC-32 标准模型,最后通过标准测试向量0x31~0x39验证校验值0xCBF43926


目录

  • 一、CRC32 简介

  • 二、CRC32 参数详解

  • 三、源代码实现

    • 3.1 crc32.h

    • 3.2 crc32.c

  • 四、使用方法与验证

    • 4.1 调用流程

    • 4.2 完整测试示例

    • 4.3 输出结果

  • 五、与在线工具对比

  • 六、总结


一、CRC32 简介

CRC(Cyclic Redundancy Check)是一种广泛应用于数据通信和存储的查错校验码。CRC32 生成长度为 32 位的校验值,常用于 ZIP、GZIP、以太网等协议中。
本文实现的算法模型是常见的CRC-32/ISO-HDLC,其多项式为0xEDB88320,也是 Pythonbinascii.crc32zlib.crc32的默认算法。


二、CRC32 参数详解

一个标准的 CRC 模型由以下参数决定,下文结合代码逐一解释:

参数含义
width32CRC 值的位宽,32 位。
poly0xEDB88320生成多项式(反射形式)。原始多项式为0x04C11DB7,反射后即为该值。
init0xFFFFFFFF寄存器初始值。参与计算前 CRC 寄存器的初值。
RefIntrue输入是否按位反射。true表示每个字节先进行位反转再处理。
RefOuttrue输出是否按位反射。true表示最终 CRC 值整体位反转。
XorOut0xFFFFFFFF输出异或值。在最终结果输出前,将 CRC 值与该值异或。
Check0xCBF43926标准校验值。对 ASCII 字符串"123456789"(十六进制0x31~0x39)计算得到的 CRC32。

参数如何体现在代码中

  • init:函数CRC32_Init将寄存器初始化为0xFFFFFFFF

  • poly:在CheckCrc32中,当移出的位为 1 时,用0xEDB88320异或。

  • RefIn / RefOut:代码中直接逐位处理最低位,并采用反射多项式0xEDB88320,这等价于自动实现了输入和输出的位反射。因此无需额外反转函数,计算结果本身就符合RefIn=true, RefOut=true的模型。

  • XorOut:函数CheckCrc32_Result在最终返回前将 CRC 值与0xFFFFFFFF异或。

注意:由于采用了反射多项式,该算法也被称为“直接表驱动法”的按位实现,省去了繁复的位反转步骤。


三、源代码实现

下面给出完整可用的crc32.hcrc32.c

3.1 crc32.h

/*=========================================================================== crc32校验 1. crc32相关参数如下 width: 32 poly: 0xEDB88320 init: 0xffffffff RefIn: true RefOut: true XorOut: 0xffffffff Check: 0xCBF43926(输入0x31~0x39计算所得) ============================================================================*/ #ifndef __CRC32_H__ #define __CRC32_H__ #ifdef _CRC32_C_ //定义数据类型 #ifndef uint8_t //8位无符号数 #define uint8_t unsigned char #endif #ifndef uint16_t//16位无符号数 #define uint16_t unsigned short #endif #ifndef uint32_t//32位无符号数 #define uint32_t unsigned long #endif //crc相关参数设置 #define CRC_INIT_VALUE 0xffffffffuL //crc32的初始值,即init #define CRC_POL_VALUE 0xEDB88320uL //crc32的多项式,即poly #define CRC_OUT_XOR 0xffffffffuL //crc32的输出xor值,即XorOut #endif /***************************************************************************** 功能描述: crc32的初始值 *****************************************************************************/ void CRC32_Init(uint32_t *pCrc); /***************************************************************************** 功能描述: 计算1个byte的crc32 *****************************************************************************/ void CheckCrc32(uint8_t data, uint32_t *pCrc); /***************************************************************************** 功能描述: 计算一串数据的crc32 *****************************************************************************/ void CheckCrc32_nBytes(const uint8_t* data, uint16_t len, uint32_t *pCrc); /***************************************************************************** 功能描述: crc32的最终异或输出 *****************************************************************************/ uint32_t CheckCrc32_Result(uint32_t crc); #endif

3.2 crc32.c

#define _CRC32_C_ #include "Crc32.h" /***************************************************************************** 功能描述: crc32的初始值 *****************************************************************************/ void CRC32_Init(uint32_t *pCrc) { *pCrc = CRC_INIT_VALUE; } /***************************************************************************** 功能描述: 计算1个byte的crc32 *****************************************************************************/ void CheckCrc32(uint8_t data, uint32_t *pCrc) { uint32_t i = 0u; uint32_t temp = *pCrc; temp ^= data; for (i = 0u; i < 8u; i++) { if (temp & 0x1uL) { temp >>= 1; temp ^= CRC_POL_VALUE; } else { temp >>= 1; } } *pCrc = temp; } /***************************************************************************** 功能描述: 计算一串数据的crc32 *****************************************************************************/ void CheckCrc32_nBytes(const uint8_t* data, uint16_t len, uint32_t *pCrc) { uint16_t i; uint32_t temp = *pCrc; uint8_t oneByte; for(i = 0u; i < len; i++) { oneByte = *data; CheckCrc32(oneByte, &temp); data++; } *pCrc = temp; } /***************************************************************************** 功能描述: crc32的最终异或输出 *****************************************************************************/ uint32_t CheckCrc32_Result(uint32_t crc) { return (crc ^ CRC_OUT_XOR); }

四、使用方法与验证

4.1 调用流程

  1. 定义uint32_t类型变量用于存放 CRC 中间值。

  2. 调用CRC32_Init(&crc)初始化寄存器。

  3. 多次调用CheckCrc32_nBytes或循环调用CheckCrc32输入待校验数据。

  4. 最后调用CheckCrc32_Result(crc)得到最终 CRC32 校验值。

4.2 完整测试示例

创建main.c,用标准测试数据"123456789"(十六进制0x31 0x32 ... 0x39)验证校验值0xCBF43926

#include <stdio.h> #include "Crc32.h" int main(void) { // 标准测试数据:123456789 对应的 ASCII 码 const uint8_t testData[] = {0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39}; uint32_t crc; // 1. 初始化 CRC32_Init(&crc); // 2. 计算所有字节 CheckCrc32_nBytes(testData, sizeof(testData), &crc); // 3. 异或输出得到最终结果 crc = CheckCrc32_Result(crc); // 4. 打印结果并与标准Check值对比 printf("Calculated CRC32: 0x%08X\n", crc); printf("Expected Check : 0xCBF43926\n"); if (crc == 0xCBF43926uL) { printf("CRC32 verification passed!\n"); } else { printf("CRC32 verification failed!\n"); } // 附加示例:计算字符串 "Hello, CSDN!" 的 CRC32 char str[] = "Hello, CSDN!"; CRC32_Init(&crc); CheckCrc32_nBytes((const uint8_t*)str, (uint16_t)(sizeof(str)-1), &crc); crc = CheckCrc32_Result(crc); printf("CRC32 of \"%s\": 0x%08X\n", str, crc); return 0; }

4.3 输出结果

运行程序后控制台将输出:

Calculated CRC32: 0xCBF43926 Expected Check : 0xCBF43926 CRC32 verification passed! CRC32 of "Hello, CSDN!": 0x37A54F16

与预期完全一致,证明算法实现正确。


五、与在线工具对比

可以将程序计算出的Hello, CSDN!的 CRC32 值与在线 CRC 计算器对比。
选择模型为CRC-32(poly=0xEDB88320, init=0xFFFFFFFF, RefIn/RefOut=true, XorOut=0xFFFFFFFF),计算结果同样为0x37A54F16,再次验证代码的可靠性。


六、总结

  • 本文详细解析了 CRC32 的六项关键参数,并通过代码展示了它们的具体作用。

  • 提供的 C 语言实现小巧、无第三方依赖,可直接嵌入单片机或嵌入式项目中。

  • 使用标准测试数据0xCBF43926完成了正确性校验,读者可放心使用。

  • 实际应用中只需包含Crc32.hCrc32.c,按初始化 → 输入数据 → 读取结果的步骤调用即可。

http://www.jsqmd.com/news/1155583/

相关文章:

  • SPI-NAND vs Raw NAND vs SPI-NOR:3种存储方案在Linux MTD子系统下的性能与选型对比
  • Citra 3DS模拟器终极指南:免费畅玩任天堂3DS游戏的完整方案
  • 政策兑现时如何构建企业历史信用与创新表现的可追溯记录?
  • 消费级桌面创客工具催生创业潮:普通人的创作自由与小众生意的生命力
  • 2026山东省电大中专/成人中专官方报名入口 - 小张zc
  • 2026版Linux运维实战教程:零基础入门到就业全链路指南
  • 140.IEC61131-3 实战!扫描周期优化 + 边沿防抖 + 精准时序控制工程
  • 计算DSA的时间复杂度
  • 2026快递瓦楞纸箱定制厂家盘点:源头工厂实力与推荐万利兴 - 栗子测评
  • 全2026年北京市煤改电补贴政策QA(用户最关心的问题) - 十大品牌榜
  • 【上海立信会计金融学院本科毕业论文】基于Spring Boot的餐厅管理系统设计与实现
  • Tabby分屏功能终极指南:现代终端的多任务管理利器
  • 2026年最新上海geo优化公司——上海企业从入门到选型的实操指南 - 资讯焦点
  • 嵌入式电源管理:MAX77654与PIC32MX695F512L高效方案
  • 2026年宁波刑事律师推荐精选:5位经验丰富值得了解 - 本地品牌推荐
  • 2026跨境社媒运营避坑指南:这几个被忽略的长尾流量技巧帮你轻松拿平台推荐
  • Save Image as Type终极指南:一键转换网页图片格式的Chrome扩展
  • 石家庄黄金奢侈品回收哪家靠谱?正规门店、价格、流程全方位测评 - 奢侈品交易观察员
  • 2026年Q1最新|安徽飞纯特种电缆卸船机电缆品牌实力TOP1 港口基建采购首选指南 - 安互工业信息
  • 深挖石家庄手表回收行业内幕,闲置劳力士欧米茄出手必看! - 奢侈品回收测评
  • 深圳闲置大牌包包变现渠道,专业鉴定估价支持到店回收 - 每日生活报
  • 2026广州名表变现完整攻略,上门回收与到店交易优劣对比 - 禹竞奢收行
  • TensorFlow 2.16 / PyTorch 2.3 GPU环境验证:5行代码排查CUDA驱动与框架版本兼容性
  • D2DX:让经典《暗黑破坏神2》在现代PC上重获新生的终极改造方案
  • HDMI 2.1 FRL 6种速率模式对比:从3 Lane 3Gbps到4 Lane 12Gbps带宽实测
  • OmniRoute:轻量级API网关从入门到生产实践
  • 氧大夫血氧仪测得准吗?从技术原理到临床实证,看清精度背后的依据 - 科技焦点
  • 金价高峰期出手必看!信阳全域上门黄金回收,流程透明现场转账交易安全攻略 - 衡金阁
  • XU316 对比 XU216 全部核心优势
  • 拒绝被坑!2026沈阳正规翡翠回收榜单,无损鉴定 + 全款极速回款 - 奢侈品回收中心