CRC32算法详细推导(3)

From:http://blog.csdn.net/sparkliang/article/details/5671543

CRC32算法详细推导(3)

郁闷的位逆转

看起来我们已经得到 CRC-32 算法的最终形式了,可是、可是在实际的应用中,数据传输时是低位先行的;对于一个字节 Byte 来讲,传输将是按照 b1,b2,...,b8 的顺序。而我们上面的算法是按照高位在前的约定,不管是 reg还是 G(x) , g32,g31,...,g1 ; b8,b7,...,b1 ; r32,r31,...,r1 。

先来看看前面从 bit 转换到 Byte 一节中 for 循环的逻辑:

[cpp] view plaincopy
  1.               sum_poly = reg&0xFF000000;  
  2. for(int j = 0; j < 8; j++)  
  3. {  
  4.     int hi = sum_poly&0x80000000; // 测试reg最高位  
  5.     sum_poly <<= 1;  
  6.     if(hi) sum_poly = sum_poly^POLY;  
  7. }  
  8. // 计算步骤2  
  9. reg = (reg<<8)|p[i];  
  10. reg = reg ^ sum_poly;  

在这里的计算中, p[i] 是按照 p8,p7,...,p1 的顺序;如果 p[i] 在这里变成了 p1,p2,...,p8 的顺序;那么 reg 也应该是 r1,r2,...,r32 的顺序,同样 G(x) 和 sum_poly 也要逆转顺序。转换后的 G(x) = POLY = 0xEDB88320 。

于是取 reg 的最高位的 sum_poly 的初值就从 sum_poly = reg & 0xFF000000 变成了 sum_poly = reg & 0xFF,测试 reg 的最高位就从 sum_poly & 0x80000000 变成了 sum_poly&0x01 ;

移出最高位也就从 sum_poly<<=1 变成了 sum_poly>>=1 ;于是上面的代码就变成了如下的形式:

[cpp] view plaincopy
  1.               sum_poly = reg&0xFF;  
  2. for(int j = 0; j < 8; j++)  
  3. {  
  4.     int hi = sum_poly&0x01; // 测试reg最高位  
  5.     sum_poly >>= 1;  
  6.     if(hi) sum_poly = sum_poly^POLY;  
  7. }  
  8. // 计算步骤2  
  9. reg = (reg<<8)|p[i];  
  10. reg = reg ^ sum_poly;  

为了清晰起见,给出完整的代码:

[cpp] view plaincopy
  1. // 以4 byte数据为例  
  2. #define POLY 0xEDB88320L // CRC32生成多项式  
  3. unsigned int CRC32_2(unsigned int data)  
  4. {  
  5.     unsigned char p[8];  
  6.     memset(p, 0, sizeof(p));  
  7.     memcpy(p, &data, 4);  
  8.     unsigned int reg = 0, sum_poly = 0;  
  9.     for(int i = 0; i < 8; i++)  
  10.     {  
  11.         // 计算步骤1  
  12.         sum_poly = reg&0xFF;  
  13.         for(int j = 0; j < 8; j++)  
  14.         {  
  15.             int hi = sum_poly&0x01; // 测试reg最高位  
  16.             sum_poly >>= 1;  
  17.             if(hi) sum_poly = sum_poly^POLY;  
  18.         }  
  19.         // 计算步骤2  
  20.         reg = (reg<<8)|p[i];  
  21.         reg = reg ^ sum_poly;  
  22.     }  
  23.     return reg;  
  24. }  

依旧像上面的思路,把计算 sum_poly 的代码段提取出来,生成 256 个元素的 CRC 校验表,再修改追加 0 的逻辑,最终的代码版本就完成了,为了对比;后面给出了字节序逆转前的完整代码段。

[cpp] view plaincopy
  1. // 字节逆转后的CRC32算法,字节序为b1,b2,…,b8  
  2. #define POLY 0xEDB88320L // CRC32生成多项式  
  3. static unsigned int crc_table[256];  
  4. unsigned int get_sum_poly(unsigned char data)  
  5. {  
  6.     unsigned int sum_poly = data;  
  7.     for(int j = 0; j < 8; j++)  
  8.     {  
  9.         int hi = sum_poly&0x01; // 取得reg的最高位  
  10.         sum_poly >>= 1;  
  11.         if(hi) sum_poly = sum_poly^POLY;  
  12.     }  
  13.     return sum_poly;  
  14. }  
  15. void create_crc_table()  
  16. {  
  17.     for(int i = 0; i < 256; i++)  
  18.     {  
  19.         crc_table[i] = get_sum_poly(i&0xFF);  
  20.     }  
  21. }   
  22. unsigned int CRC32_4(unsigned char* data, int len)  
  23. {  
  24.     unsigned int reg = 0; // 0xFFFFFFFF,见后面解释  
  25.     for(int i = 0; i < len; i++)  
  26.     {  
  27.         reg = (reg<<8) ^ crc_table[(reg&0xFF) ^ data[i]];  
  28.         return reg;  
  29.     }  
  30. }  
  31. // 最终生成的校验表将是:  
  32. // {0x00000000,  0x77073096,  0xEE0E612C,  0x990951BA,  
  33. //  0x076DC419,  0x706AF48F,  0xE963A535,  0x9E6495A3,  
  34. // … …}   
  35. // 字节逆转前的CRC32算法,字节序为b8,b7,…,b1  
  36. #define POLY 0x04C11DB7L // CRC32生成多项式  
  37. static unsigned int crc_table[256];  
  38. unsigned int get_sum_poly(unsigned char data)  
  39. {  
  40.     unsigned int sum_poly = data;  
  41.     sum_poly <<= 24;  
  42.     for(int j = 0; j < 8; j++)  
  43.     {  
  44.         int hi = sum_poly&0x80000000; // 取得reg的最高位  
  45.         sum_poly <<= 1;  
  46.         if(hi) sum_poly = sum_poly^POLY;  
  47.     }  
  48.     return sum_poly;  
  49. }  
  50. void create_crc_table()  
  51. {  
  52.     for(int i = 0; i < 256; i++)  
  53.     {  
  54.         crc_table[i] = get_sum_poly(i&0xFF);  
  55.     }  
  56. }   
  57. unsigned int CRC32_4(unsigned char* data, int len)  
  58. {  
  59.     unsigned int reg = 0;// 0xFFFFFFFF,见后面解释  
  60.     for(int i = 0; i < len; i++)  
  61.     {  
  62.         reg = (reg<<8) ^ crc_table[(reg>>24)&0xFF ^ data[i]];  
  63.         return reg;  
  64.     }  
  65. }  

长征结束了

到这里长征终于结束了, 事实上,还有最后的一小步,那就是 reg 初始值的问题,上面的算法中 reg 初始值为 0 。在一些传输协议中,发送端并不指出消息长度,而是采用结束标志,考虑下面的这几种可能的差错:

1 )在消息之前,增加 1 个或多个 0 字节;

2) 在消息 ( 包括校验码 ) 之后,增加 1 个或多个 0 字节;

显然,这几种差错都检测不出来,其原因就是如果 reg=0 ,处理 0 消息字节 ( 或位 ) , reg 的值保持不变。解决这种问题也很简单,只要使 reg 的初始值非 0 即可,一般取 0Xffffffff ,就像你在很多 CRC32 实现中发现的那样。

到这里终于可以松一口气了, CRC32 并不是像想象的那样容易的算法啊!事实上还真不容易!这就叫做“简单的前面是优雅,背后是复杂”!


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/404150.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WebService的学习

这篇文章不错&#xff0c;直接转了 http://blog.csdn.net/terryzero/article/details/5976638#comments 转载于:https://www.cnblogs.com/zhilu-doc/p/5291927.html

linux 用户行为审计

根据公司需求&#xff0c;整理了一个linux用户审计的脚本&#xff0c;现和大家分享&#xff01; 具体步骤如下&#xff1a; 一&#xff1a;配置调试 1.创建用户审计文件存放目录和审计日志文件 &#xff1b; mkdir -p /var/log/usermonitor/ 2.创建用户审计日志文件&#xff1…

前端面试题vue-element汇总

【Vue-element】 [vue-element] ElementUI是怎么做表单验证的&#xff1f;在循环里对每个input验证怎么做呢&#xff1f; [vue-element] 你有二次封装过ElementUI组件吗&#xff1f; [vue-element] ElementUI怎么修改组件的默认样式&#xff1f; [vue-element]ElementUI的穿…

每天一点Swift(五)控制器的生命周期和SizeClass

字数358 阅读19 评论0 喜欢0 初始化init-->awakeFromNib--> prepare a segue --> SB去设置outlets --> viewDidLoad 1. viewDidLoad 在viewDidLoad中&#xff0c;outlets已经被设置&#xff1b;但是几何位置&#xff08;bounds&#xff09;并没有被设置 viewDidLoa…

h264 I帧的判断

From:http://blog.csdn.net/dxpqxb/article/details/13289205 H264数据的NALU 头的格式如图2 所示&#xff1a; F&#xff1a;forbidden_zero_bit.1 位&#xff0c;如果有语法冲突&#xff0c;则为 1。当网络识别此单元存在比特错误时&#xff0c;可将其设为 1&#xff0c;以便…

前端面试题node.js汇总

【NodeJs】 [NodeJs] 你有使用过npx吗&#xff1f;它主要解决什么问题&#xff1f; [NodeJs] 如何使用nodejs对base64进行编解码&#xff1f; [NodeJs] npm提供了哪些钩子&#xff1f;各有什么作用&#xff1f; [NodeJs] 如果发现node_modules中有个模块代码有bug&#xff…

win10 下安装、配置、启动mysql

1、下载http://dev.mysql.com/downloads/mysql/ 2、Community > MySQL Community Server 3、Other Downloads: > Windows (x86, 32-bit), ZIP Archive 5、解压mysql-5.7.11-winx64.zip&#xff0c;解压在 D:\soft\mysql-5.7.11-winx64\mysql-5.7.11-winx64 6、在D:\soft\…

成功驱动HD4600-Clover引导

本人机器配置如下&#xff1a; 操作系统 Windows 7 旗舰版 64位 SP1 ( DirectX 11 ) 处理器 英特尔 Core i7-4770K 3.50GHz 四核 核显&#xff1a; Intel HD4600 主板 华硕 Z87-PRO (英特尔 Haswell) 内存 8 GB ( 金士顿 DDR3 1778MH…

前端软技能面试汇总

【软技能】 [软技能] 在前后端分离项目里&#xff0c;请说说前端传递的token的流程&#xff1f; [软技能] 现如今面对如层出不穷的类库&#xff0c;说说你的感受 [软技能] 你认为计算专业和非计算机专业的差别在哪&#xff1f;为什么&#xff1f; [软技能] png-8和png-24有…

ACM训练计划(上)

一.基本算法: (1)枚举.(poj1753,poj2965) (2)贪心.(poj1328,poj2109,poj2586) (3)递归和分治法. (4)递推. (5)构造法.(poj3295) (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)二.图算法: (1)图的深度优先遍历和广度优先遍历. (2)最短路…

单硬盘上mac + win7双系统,GUID-GPT分区

首先&#xff0c;当然要介绍下我的环境了。 一、环境介绍 1. 主板是支持UEFI启动的&#xff0c;但是我感觉自己没用到。 2. 我有两个硬盘: hd0: 准备安装mac和win7_x64 hd1: GUID格式&#xff0c;GPT分区&#xff0c;已装有mac10.9.3环境&#xff0c;还有个FAT32的分区&a…

React开发(273):异步调用的方式

1、回调函数方式 doFirstThing((err, data) > {if (err) {console.log(err);return;}doSecondThing(data, function(err, data){if (err) {console.log(err);return;}doThirdThing(data, function(err, data){if (err) {console.log(err);return;}})}) })2、Promise 方式 …

hdu 1166 敌兵布阵 (线段树)

http://acm.hdu.edu.cn/showproblem.php?pid1166最基础的线段树&#xff0c;单点更新。完全跟着HH的代码风格写的。code:#include<cstdio>#define lson l, m, rt<<1#define rson m1, r, rt<<1|1const int maxn 50005 ;int sum[maxn<<2] ;void PushUp…

将clover安装到硬盘EFI分区, 解决root device uuid is ...问题

其实说白了&#xff0c;很简单&#xff0c;照着配置图来&#xff0c;一招搞定&#xff0c;但是当你不知道这些配置的时候&#xff0c;将可能耗费你好几天的时间&#xff0c;而且还不一定得到最优解。 附“Clover v2k r2703.pkg"下载地址: http://download.csdn.net/deta…

IndiaHacks 2016 - Online Edition (Div. 1 + Div. 2) C. Bear and Up-Down 暴力

C. Bear and Up-Down题目连接&#xff1a; http://www.codeforces.com/contest/653/problem/C Description The life goes up and down, just like nice sequences. Sequence t1, t2, ..., tn is called nice if the following two conditions are satisfied: ti < ti …

Silverlight 5 新特性

微软Silverlight 团队在12月9日早上低调的发布了Silverlight 第五个版本-Silverlight 5. Silverlight 5 Available is Here 这也可能是Silverlight最后一个官方主要版本. Silverlight 5 可能作为官方发布最后一个Silverlight 版本. 官方提供各方面支持直到2021年. 支持的时间相…

VMware10出现VMware Workstation 不可恢复错误: (vmx)

在我的VMware10中安装了Ubuntu12&#xff0c; 昨晚还正常关机的呢&#xff0c;今天早上一打开&#xff0c;竟然报错了&#xff0c;错误如图&#xff1a; 上网搜索了下&#xff0c;没有找到比较合适的方法&#xff0c;最后&#xff0c;我在没有卸载VMware的情况下&#xff0c;重…

DB2中ixf文件的导入导出

1. 导出数据 语法&#xff1a;EXPORT TO <文件路径>/文件名.IXF OF IXF SELECT * FROM 表名 2. 导入数据 语法&#xff1a;db2 IMPORT FROM <路径>/<文件名>.IXF OF IXF MODIFIED BY FORCECREATE COMMITCOUNT 10000 REPLACE_CREATE INTO <表名> 简单语…