生活随笔
收集整理的這篇文章主要介紹了
                                
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  
??????????????sum_poly?=?reg&0xFF000000;??for(int?j?=?0;?j?<?8;?j++)??{??????int?hi?=?sum_poly&0x80000000;?//?測試reg最高位??????sum_poly?<<=?1;??????if(hi)?sum_poly?=?sum_poly^POLY;??}??//?計算步驟2??reg?=?(reg<<8)|p[i];??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  
??????????????sum_poly?=?reg&0xFF;??for(int?j?=?0;?j?<?8;?j++)??{??????int?hi?=?sum_poly&0x01;?//?測試reg最高位??????sum_poly?>>=?1;??????if(hi)?sum_poly?=?sum_poly^POLY;??}??//?計算步驟2??reg?=?(reg<<8)|p[i];??reg?=?reg?^?sum_poly;?? 
 
為了清晰起見,給出完整的代碼:
 
 
  [cpp]?view plaincopy  
//?以4?byte數據為例??#define?POLY?0xEDB88320L?//?CRC32生成多項式??unsigned?int?CRC32_2(unsigned?int?data)??{??????unsigned?char?p[8];??????memset(p,?0,?sizeof(p));??????memcpy(p,?&data,?4);??????unsigned?int?reg?=?0,?sum_poly?=?0;??????for(int?i?=?0;?i?<?8;?i++)??????{??????????//?計算步驟1??????????sum_poly?=?reg&0xFF;??????????for(int?j?=?0;?j?<?8;?j++)??????????{??????????????int?hi?=?sum_poly&0x01;?//?測試reg最高位??????????????sum_poly?>>=?1;??????????????if(hi)?sum_poly?=?sum_poly^POLY;??????????}??????????//?計算步驟2??????????reg?=?(reg<<8)|p[i];??????????reg?=?reg?^?sum_poly;??????}??????return?reg;??}?? 
 
依舊像上面的思路,把計算?sum_poly?的代碼段提取出來,生成?256?個元素的?CRC?校驗表,再修改追加?0?的邏輯,最終的代碼版本就完成了,為了對比;后面給出了字節序逆轉前的完整代碼段。
 
 
  [cpp]?view plaincopy  
//?字節逆轉后的CRC32算法,字節序為b1,b2,…,b8??#define?POLY?0xEDB88320L?//?CRC32生成多項式??static?unsigned?int?crc_table[256];??unsigned?int?get_sum_poly(unsigned?char?data)??{??????unsigned?int?sum_poly?=?data;??????for(int?j?=?0;?j?<?8;?j++)??????{??????????int?hi?=?sum_poly&0x01;?//?取得reg的最高位??????????sum_poly?>>=?1;??????????if(hi)?sum_poly?=?sum_poly^POLY;??????}??????return?sum_poly;??}??void?create_crc_table()??{??????for(int?i?=?0;?i?<?256;?i++)??????{??????????crc_table[i]?=?get_sum_poly(i&0xFF);??????}??}???unsigned?int?CRC32_4(unsigned?char*?data,?int?len)??{??????unsigned?int?reg?=?0;?//?0xFFFFFFFF,見后面解釋??????for(int?i?=?0;?i?<?len;?i++)??????{??????????reg?=?(reg<<8)?^?crc_table[(reg&0xFF)?^?data[i]];??????????return?reg;??????}??}??//?最終生成的校驗表將是:??//?{0x00000000,??0x77073096,??0xEE0E612C,??0x990951BA,??//??0x076DC419,??0x706AF48F,??0xE963A535,??0x9E6495A3,??//?…?…}???//?字節逆轉前的CRC32算法,字節序為b8,b7,…,b1??#define?POLY?0x04C11DB7L?//?CRC32生成多項式??static?unsigned?int?crc_table[256];??unsigned?int?get_sum_poly(unsigned?char?data)??{??????unsigned?int?sum_poly?=?data;??????sum_poly?<<=?24;??????for(int?j?=?0;?j?<?8;?j++)??????{??????????int?hi?=?sum_poly&0x80000000;?//?取得reg的最高位??????????sum_poly?<<=?1;??????????if(hi)?sum_poly?=?sum_poly^POLY;??????}??????return?sum_poly;??}??void?create_crc_table()??{??????for(int?i?=?0;?i?<?256;?i++)??????{??????????crc_table[i]?=?get_sum_poly(i&0xFF);??????}??}???unsigned?int?CRC32_4(unsigned?char*?data,?int?len)??{??????unsigned?int?reg?=?0;//?0xFFFFFFFF,見后面解釋??????for(int?i?=?0;?i?<?len;?i++)??????{??????????reg?=?(reg<<8)?^?crc_table[(reg>>24)&0xFF?^?data[i]];??????????return?reg;??????}??}?? 
 
長征結束了
 
到這里長征終于結束了,?事實上,還有最后的一小步,那就是?reg?初始值的問題,上面的算法中?reg?初始值為?0?。在一些傳輸協議中,發送端并不指出消息長度,而是采用結束標志,考慮下面的這幾種可能的差錯:
 
1?)在消息之前,增加?1?個或多個?0?字節;
 
2)?在消息?(?包括校驗碼?)?之后,增加?1?個或多個?0?字節;
 
顯然,這幾種差錯都檢測不出來,其原因就是如果?reg=0?,處理?0?消息字節?(?或位?)?,?reg?的值保持不變。解決這種問題也很簡單,只要使?reg?的初始值非?0?即可,一般取?0Xffffffff?,就像你在很多?CRC32?實現中發現的那樣。
 
到這里終于可以松一口氣了,?CRC32?并不是像想象的那樣容易的算法啊!事實上還真不容易!這就叫做“簡單的前面是優雅,背后是復雜”!
 
                            總結
                            
                                以上是生活随笔為你收集整理的CRC32算法详细推导(3)的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                            
                                如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。