CRC32算法详细推导(3)

来源:互联网 发布:linux系统装在哪个分区 编辑:程序博客网 时间:2024/04/30 02:56

CRC32算法详细推导(3)

郁闷的位逆转

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

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

在这里的计算中,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;于是上面的代码就变成了如下的形式:

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

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

长征结束了

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

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

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

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

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

 

 

 

 

 

原创粉丝点击