CRC32 例程與理解

原理

原理我就不詳細介紹了,維基百科什么的有很多,大概意思就是這么一套操作過后可以極大概率地檢測出數據錯誤。我又怎么會告訴你們我也沒有完全看懂。

實現

直接計算法

/**
 * CRC32 校驗函數
 * @param pdata 數據指針
 * @param len 數據長度
 * @param crc 初值或上段數據校驗結果
 * @param poly 多項式
 */
uint32_t CRC32(const uint8_t* pdata, int len, uint32_t crc, uint32_t poly)
{
    for (int i = 0; i < len; i++, pdata++)
    {
        crc ^= ((uint32_t)*pdata << 24);

        for (int bits = 0; bits < 8; bits++)
        {
            if (crc & 0x80000000)
            {
                crc = (crc << 1) ^ poly;
            }
            else
            {
                crc <<= 1;
            }
        }
    }
    return crc;
}

稍微解釋一下代碼,大概步驟是:

  1. 把新的數據 xor 到之前數據的最高 byte
  2. 判斷最高 bit,如果是 0 就左移,是 1 就左移后 xor poly
  3. 處理完最高 8 個 bits 結束

網上有些例程是右移處理,其實本質是一樣的,只要生成 CRC 的程序和校驗它的程序是一致的就可以。

為了證明我不是隨便找了一段沒驗證過的代碼就貼出來,我這里給出一個 CRC Online Calculator,我貼出的代碼能夠得出和它一致的結果,各位自己調試代碼的時候也可以有個參考。

使用的時候有幾點注意:

  • 選擇 CRC-32
  • 由于我給出的代碼沒有進行位翻轉操作,所以選擇 Custom,然后兩個 reflected 的鉤去掉
  • Final Xor Value 填 0
  • 剩下的你應該懂的

雖然這段代碼簡單明白,但是網上類似的東西也不少,發個貼子沒點干貨似乎不太好意思。那么我就多給點料。

查表法

了解多一些的朋友會知道,雖然直接計算的方法代碼特別簡單,但是循環次數太多效率不夠高。根據 xor 運算的結合律特性,可以使用查表法提高運行效率。

static uint32_t gsTable[256];

void CRC32_TableInit(uint32_t poly)
{
    for(uint32_t i = 0; i < 256; i++)
    {
        uint32_t crc = i << 24;

        for (int bits = 0; bits < 8; bits++)
        {
            if (crc & 0x80000000)
            {
                crc = (crc << 1) ^ poly;
            }
            else
            {
                crc <<= 1;
            }
        }

        gsTable[i] = crc;
    }
}

uint32_t CRC32_Table(const uint8_t* pdata, int len, uint32_t crc)
{
    uint8_t index;

    for (int i = 0; i < len; i++, pdata++)
    {
        index = *pdata ^ (crc >> 24);
        crc = (crc << 8) ^ gsTable[index];
    }
    return crc;
}

對比上面的代碼,其實就是把 8 bits 的循環抽了出來。從直接計算的代碼我們看出,這八次循環的計算效果,其實完全取決于新數據 xor 之后 crc 最高 byte 的值。那么我們如果把這一個 byte 所有可能的值對應的計算結果先存起來,就得到了一個 256 數據的表。

使用的時候就拿 xor 之后的最高 byte 去查表,然后把 crc 直接左移 8 個 bits,再進行一次 xor 就妥了。

有些朋友會疑惑,這樣一番操作是不是真的能得到同樣的結果。我們可以觀察一下表的值,發現它的第 0 個值必然是 0,而第 1 個值,必然等于 poly。為什么呢?因為如果最高 byte 是 0 的話,數據除了會左移 8 個 bits 以外,剩下的 bits 都不會改變(xor 0 值也不變)。而最高 byte 如果是 1 的話,那么它會在第 8 次左移之后 xor 一次 poly。可以看出至少在這兩種情況的時候,兩段代碼的計算效果是等價的,而后面的更多種情況就只能自己體會一下了。

查表法是挺不錯,但是網上其實也能找得到。所以呢,就再上一份干貨,這是我實際踩過的坑。

STM32 CRC32

下面的代碼,與 STM32 中自帶的 CRC32 模塊的計算效果是等效的。

#define CRC_STM32_POLY          0x04c11db7
#define CRC_STM32_INIT_VALUE    0xFFFFFFFF

uint32_t STM32_CRC32(const uint32_t* pdata, int len, uint32_t crc, uint32_t poly)
{
    for (int i = 0; i < len; i++, pdata++)
    {
        crc ^= *pdata;

        for (int bits = 0; bits < 32; bits++)
        {
            if ((crc & 0x80000000) != 0)
            {
                crc = (crc << 1) ^ poly;
            }
            else
            {
                crc <<= 1;
            }
        }
    }
    return crc;
}

那么它和我們上面一般的 CRC 運算有什么不同呢?細心的朋友可能發現了,它的計算是 32 bits 一輪的,而由于其是小端存儲,所以其實是從第四個 byte 的最高 bit 開始計算的。和從第一個 byte 開始計算的 CRC 結果是不一樣的,而且輸入數據 bytes 個數必須補零到 4 的整數倍。

如果你以為它和一開始介紹的算法一樣,就會被它坑到 T^T。而它的算法是內置的,沒得修改,所以只要你想用,就必須按它的來。

好了,干貨上完,感謝閱讀。

Jalon 原創,轉載署名,商用聯系本人。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,048評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,414評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,169評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,722評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,465評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,823評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,813評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,000評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,554評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,295評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,513評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,722評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,125評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,430評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,237評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,482評論 2 379

推薦閱讀更多精彩內容