日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CRC32算法详细推导(3)

發(fā)布時間:2023/12/9 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CRC32算法详细推导(3) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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

CRC32算法詳細推導(3)

郁悶的位逆轉

看起來我們已經得到?CRC-32?算法的最終形式了,可是、可是在實際的應用中,數據傳輸時是低位先行的;對于一個字節(jié)?Byte?來講,傳輸將是按照?b1,b2,...,b8?的順序。而我們上面的算法是按照高位在前的約定,不管是?reg還是?G(x)?,?g32,g31,...,g1?;?b8,b7,...,b1?;?r32,r31,...,r1?。

先來看看前面從?bit?轉換到?Byte?一節(jié)中?for?循環(huán)的邏輯:

[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?的邏輯,最終的代碼版本就完成了,為了對比;后面給出了字節(jié)序逆轉前的完整代碼段。

    [cpp]?view plaincopy
  • //?字節(jié)逆轉后的CRC32算法,字節(jié)序為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,??
  • //?…?…}???
  • //?字節(jié)逆轉前的CRC32算法,字節(jié)序為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?。在一些傳輸協議中,發(fā)送端并不指出消息長度,而是采用結束標志,考慮下面的這幾種可能的差錯:

    1?)在消息之前,增加?1?個或多個?0?字節(jié);

    2)?在消息?(?包括校驗碼?)?之后,增加?1?個或多個?0?字節(jié);

    顯然,這幾種差錯都檢測不出來,其原因就是如果?reg=0?,處理?0?消息字節(jié)?(?或位?)?,?reg?的值保持不變。解決這種問題也很簡單,只要使?reg?的初始值非?0?即可,一般取?0Xffffffff?,就像你在很多?CRC32?實現中發(fā)現的那樣。

    到這里終于可以松一口氣了,?CRC32?并不是像想象的那樣容易的算法啊!事實上還真不容易!這就叫做“簡單的前面是優(yōu)雅,背后是復雜”!


    總結

    以上是生活随笔為你收集整理的CRC32算法详细推导(3)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。