C语言标准CRC-32校验函数

CRC-32校验产生4个字节长度的数据校验码,通过计算得到的校验码和获得的校验码比较,用于验证获得的数据的正确性。获得的校验码是随数据绑定获得。

CRC校验原理及标准CRC-8校验函数可参考:C语言标准CRC-8校验函数。这里介绍CRC-32的64位计算方式和简化的32位计算方式。

设计原理

设计原理仍然基于无符号64位整型为一个计算单元,当超过64位时,将前一个单元的计算余数,与后面的输入数据重新组成64位数据,再进行模二除法,以此类推,得到最后的CRC-32校验值(余数)。设计按照CRC计算基本原理来实现,以契合理解对照。

CRC-32校验函数

这里的校验码采用标准校验码x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1,对于其它类型的CRC-32校验码或有输入数据前处理或输出数据后处理的情况,相应的做代码简单调整即可。CRC-32校验函数如下:

#include <stdio.h>
#include <stdlib.h>
uint32_t PY_CRC_32(uint8_t *di, uint32_t len)
{uint64_t crc_poly = 0x104C11DB7;  //X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+1 total 33 effective bits. Computed total data shall be compensated 32-bit '0' before CRC computing.uint8_t *datain;uint64_t cdata = 0; //Computed total datauint64_t data_t = 0; //Process data of CRC computinguint16_t index_t = 63;  ///bit shifting index for initial '1' searchinguint16_t index = 63;    //bit shifting index for CRC computinguint8_t rec = 0; //bit number needed to be compensated for next CRC computinguint32_t cn=(len+4)/4;uint32_t cr=(len+4)%4;uint32_t j;datain = malloc(len+4);for(j=0;j<len;j++){datain[j]=di[j];}datain[len]=0; datain[len+1]=0; datain[len+2]=0; datain[len+3]=0;//Compensate 32-bit '0' for input dataif(len<=4)   //Mount data for only one segment{for(j=0;j<=(len+3);j++){cdata = (cdata<<8);cdata = cdata|datain[j];}cn = 1;}else{if(cr==0){cr = 8;cn--;}else if(cr==1){cr = 5;}else if(cr==2){cr = 6;}else if(cr==3){cr = 7;}else;for(j=0;j<cr;j++){cdata = (cdata<<8);cdata = cdata|datain[j];}}do{cn--;while(index_t>0){if( (cdata>>index_t)&1 ){index = index_t;index_t = 0;data_t |= (cdata>>(index-32));{data_t = data_t ^ crc_poly;}while((index!=0x5555)&&(index!=0xaaaa)){for(uint8_t n=1;n<33;n++){if ((data_t>>(32-n))&1) {rec = n;break;}if (n==32) rec=33;}if((index-32)<rec){data_t = data_t<<(index-32);data_t |=  (uint64_t)((cdata<<(64-(index-32)))>>(64-(index-32)));index = 0x5555;}else{for(uint8_t i=1;i<=rec;i++){data_t = (data_t<<1)|((cdata>>(index-32-i))&1) ;}if(rec!= 33){data_t = data_t ^ crc_poly;index -= rec;}else{data_t = 0;index_t = index-32-1;index = 0xaaaa;}}}if(index==0x5555) break;}else{index_t--;if(index_t<32) break;}}if(cn>0) //next segment{cdata = data_t&0x00ffffffff;for(uint8_t k=0;k<4;k++){cdata = (cdata<<8);cdata = cdata|datain[j++];}data_t = 0;index_t = 63;  ///bit shifting index for initial '1' searchingindex = 63;    //bit shifting index for CRC computingrec = 0; //bit number needed to be compensated for next CRC computing}}while(cn>0);free(datain);return (uint32_t)data_t;
}

CRC-32校验函数32位计算方式优化

在理解了和CRC32校验原理完全一致的代码实现后,不采用64位计算方式,则可以简化代码为32位计算方式,可得到相同的校验值结果:

#include <stdio.h>
#include <stdlib.h>
uint32_t PY_CRC_32_S(uint8_t *di, uint32_t len)
{uint32_t crc_poly = 0x04C11DB7;  //X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+1 total 32 effective bits without X^32. Computed total data shall be compensated 32-bit '0' before CRC computing.uint32_t clen = len+4;uint8_t cdata[clen] ;memcpy(cdata, di, len); cdata[len]=0; cdata[len+1]=0; cdata[len+2]=0; cdata[len+3]=0;uint32_t data_t =  (((uint32_t)cdata[0]) << 24) +  (((uint32_t)cdata[1]) << 16) + (((uint32_t)cdata[2]) << 8) + cdata[3]; //CRC registerfor (uint32_t i = 4; i < clen; i++){for (uint8_t j = 0; j <= 7; j++){if(data_t&0x80000000)data_t = ( (data_t<<1) | ( (cdata[i]>>(7-j))&0x01) ) ^ crc_poly;elsedata_t = ( (data_t<<1) | ( (cdata[i]>>(7-j))&0x01) ) ;}}return data_t;
}

CRC-32校验函数查表原理优化

CRC查表原理通过输入数据分段计算(CRC-32可按四字节/单字节分段)原理实现校验码的计算,查表法有如下特点:

  1. 当前输入数据段值异或当前的查表值,得到当前的CRC计算余数
  2. 当前查表值由前一计算余数与校验码按CRC校验过程计算得到,并保存为对应前一计算余数对应的表位值
  3. 当前查表值的计算不受当前输入字段值影响,所以当前输入字段值为0且为最后字段时,当前查表值异或当前输入字段值不变,此时当前查表值即为CRC校验值结果。
  4. 由第2和3条可知,第2条在CRC校验过程计算时,移位补位时补0即可,也就不需要当前字段值进入移位补位过程。

CRC-32校验32位数据格式函数优化为如下代码,注意输入数据为32位数组:

uint32_t PY_CRC_32_T32(uint32_t *di, uint32_t len)
{uint32_t crc_poly = 0x04C11DB7;  //X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+1 total 32 effective bits without X^32.uint32_t data_t = 0; //CRC registerfor(uint32_t i = 0; i < len; i++){data_t ^= di[i]; //32-bit datafor (uint8_t j = 0; j < 32; j++){if (data_t & 0x80000000)data_t = (data_t << 1) ^ crc_poly;elsedata_t <<= 1;}}return (data_t);
}

CRC-32校验8位数据格式函数优化为如下代码,输入数据为8位数组:

uint32_t PY_CRC_32_T8(uint8_t *di, uint32_t len)
{uint32_t crc_poly = 0x04C11DB7;  //X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+1 total 32 effective bits without X^32. uint32_t data_t = 0; //CRC registerfor(uint32_t i = 0; i < len; i++){data_t ^= di[i]<<24; //8-bit datafor (uint8_t j = 0; j < 8; j++){if (data_t & 0x80000000)data_t = (data_t << 1) ^ crc_poly;elsedata_t <<= 1;}}return (data_t);
}

查表法对应输入数据分段为四字节时,采用如上几种方式任何一种,对四字节0~4294967295的输入数分别进行CRC-32校验,得到的各个校验值,也就得到查表法对应每个输入数值的查表值。因为这种表数据量太大不会被实际用
查表法对应输入数据分段为单字节时,采用如上几种方式任何一种,对单字节0~255的输入数分别进行CRC-32校验,得到的各个校验值,也就得到查表法对应每个输入数值的查表值。

以上各种针对基本原理标准的校验函数计算结果相同。

CRC-32校验注意事项

实际应用中,由于输入数据前处理和输出数据后处理的不同,产生了不同的CRC应用标准,其中一些是一些知名厂家为自己的产品定义CRC校验函数。这些处理特性包括CRC寄存器初始值设置,数据字节位反转,数据字节高位还是低位优先进入计算,输出的整个数据是否按位反转,输出数据是否和一个数异或等。常见的一些CRC-32校验特性:

另外,ST公司STM32芯片硬件CRC32计算过程特性也和上述两种计算过程特性存在差别。而这几种因为都有前处理和后处理过程特性,所以和上面介绍的原理级定义的CRC32校验函数(无前后处理)计算出来的值不同,是在CRC32标准校验函数基础上调整得到各自的CRC32校验函数。

CRC-32常用(事实标准)校验函数

CRC-32常用(事实标准)检验函数针对能够从硬件上进行比特流实时计算而设计,即每个数据的一位进来后马上就能进行CRC-32,而不必收全数据再计算。因此对应的软件CRC-32存在一些特点:

  1. 初始值预设为0xFFFFFFFF
  2. 针对数据字节的低位先传输场景,因此数据字节的低位是高优先处理的
  3. 按照字节分段进行CRC-32计算,字节放在寄存器的低字节,因此字节最低位在左高由低的最右边一位,在进行CRC计算过程时,要从最低位/最右侧位置开始判断,移位时向右移出。因为校验码高冥端也要相应对齐,所以检验码也就要做倒位序,如0x04C11DB7(0000 0100 1100 0001 0001 1101 1011 0111)倒序为了0xEDB88320(1110 1101 1011 1000 1000 0011 0010 0000)
  4. 输出异或0xFFFFFFFF

CRC-32常用(事实标准)校验函数为反向算法(反向算法是从由右向左计算,也即计算过程中移位时,向右移出。):

uint32_t PY_CRC_32_M(uint8_t *di, uint32_t len)
{uint32_t crc_poly = 0xEDB88320;  //Inversion bit sequence of 0x04C11DB7uint32_t data_t = 0xFFFFFFFF; //initial valuefor(uint32_t i=0; i<len; i++){data_t ^=  di[i];for (int8_t j = 8; j > 0; --j){data_t = (data_t >> 1) ^ ((data_t & 1)? crc_poly: 0);}}return data_t ^ 0xFFFFFFFF;
}

对"CRC32”的计算结果为:

通过网上工具验证:

CRC-32 STM32格式校验函数

常用CRC32校验函数来自反向CRC32算法最简化的设计思想,而STM32格式CRC32校验函数来自正向CRC32算法最简化的设计思想, 参见《C语言CRC-32 STM32格式校验函数》。

–End–

C语言标准CRC-32校验函数相关推荐

  1. CRC冗余校验码源码代码c语言,循环冗余校验码(CRC)应用总结(包括C++源码)

    最近在实习期间需要用到数据的校验,所选为CRC16,那么就在此总结一番吧. 现在此说明下什么是CRC:循环冗余码校验 英文名称为Cyclical Redundancy Check,简称CRC,它是利用 ...

  2. CRC校验原理及CRC-8简单校验函数设计

    CRC校验原理及CRC-8简单校验函数设计 CRC为循环冗余校验码,是一种常用的.具有检错.纠错能力的校验码.通常发送方在发送的数据之后,附上其CRC校验码.接收方收到数据后,也做同样的CRC校验,得 ...

  3. C语言标准CRC-8校验函数

    C语言标准CRC-8校验函数 CRC校验原理及简单CRC-8校验函数(7个输入字节以内)可参考: CRC校验原理及CRC-8简单校验函数设计 . 这里的函数是实现输入范围扩展,支持任意长度的输入字节的 ...

  4. C语言CRC-16 IBM格式校验函数

    C语言CRC-16 IBM格式校验函数 CRC-16校验产生2个字节长度的数据校验码,通过计算得到的校验码和获得的校验码比较,用于验证获得的数据的正确性.基本的CRC-16校验算法实现,参考: C语言 ...

  5. sql判断邮箱是否合法_分享一个oracle身份证校验函数,判断你的身份证是否合法...

    概述 有个朋友说能不能用函数来实现对身份证的校验,所以这里用Oracle的函数来实现,其他数据库异曲同工.. 身份证校验函数 CREATE OR REPLACE FUNCTION Func_check ...

  6. 校验码(海明校验,CRC冗余校验,奇偶校验)

    循环冗余校验码 CRC码利用生成多项式为k个数据位产生r个校验位进行编码,其编码长度为n=k+r所以又称 (n,k)码. CRC码广泛应用于数据通信领域和磁介质存储系统中. CRC理论非常复杂,一般书 ...

  7. CRC16 校验函数

    数据传输时经常会用到CRC16校验,所以这里记录一下CRC16 校验函数 crc16.h #ifndef _CRC16_H_ #define _CRC16_H_unsigned short CRC16 ...

  8. java 奇偶校验_校验码(海明校验,CRC冗余校验,奇偶校验)

    循环冗余校验码 CRC码利用生成多项式为k个数据位产生r个校验位进行编码,其编码长度为n=k+r所以又称 (n,k)码. CRC码广泛应用于数据通信领域和磁介质存储系统中. CRC理论非常复杂,一般书 ...

  9. php的数据校验,php 数据类型校验函数的简单示例

    这篇文章主要为大家详细介绍了php 数据类型校验函数的简单示例,具有一定的参考价值,可以用来参考一下. 对php中数据类型校验函数感兴趣的小伙伴,下面一起跟随512笔记的小编两巴掌来看看吧! 通过这些 ...

  10. php 表单校验函数库(判断email格式是否正确、http地址是否合法有效、手机号码是否合法)...

    /*** 表单校验函数库*//*** 判断email格式是否正确* @param $email*/ function is_email($email) {return strlen($email) & ...

最新文章

  1. 黄冈师范计算机考研,2019年黄冈师范学院计算机基础复试自命题考试大纲
  2. java jfreechart下载_jfreechart下载-JFreeChart下载安装[java图表插件]-PC下载网
  3. 看图说话:用户标签可以这样轻松创建
  4. 全国计算机等级考试题库二级C操作题100套(第87套)
  5. linux nexus启动_Linux一键部署Nexus 3私服仓库自动化部署脚本
  6. java拷贝文件目录结构_Java如何复制目录_Java基础教程系列
  7. Android WebView 调起H5支付,提示商家参数格式有误
  8. python学习笔记一:python基础知识
  9. 经典领导选举算法:Bully 算法
  10. 再见Activity!SpringBoot+flowable完美结合,快速实现工作流,so easy!
  11. 居民身份证号码查询系统
  12. matlab求两向量夹角_10373 高中立体几何向量法全攻略
  13. Android实现新浪微博和QQ登陆并获取用户的信息
  14. 计算机专业如何推广太极拳,太极拳在年轻人群体中推广的怎么样不得不说挺吃惊...
  15. 视频文件损坏无法播放怎么修复?
  16. LUOGU1438无聊的数列
  17. PADS Logic Decal、Layout Decal绘制
  18. Gitlab 设置页面语言为简体中文
  19. 国科大学习资料--最优化计算方法(王晓)--第三次作业答案
  20. 华军:坚持就是胜利(附图)

热门文章

  1. Spring data jpa Specification 子查询实现
  2. java通用返回实体类
  3. 思科ACS配置案例解析
  4. XML文件操作下之XPath
  5. 淘宝开店,为什么要对竞争对手进行分析?
  6. Python 爬虫系列:爬取全球船公司信息
  7. Python爬虫初学爬取网站天气数据
  8. OpenHarmony啃论文俱乐部收获总结
  9. 莫烦NLP学习系列:把词语向量化
  10. SAR目标检测识别中一些基本概念