【问题标题】:CRC-32 with LFSR Byte by Byte in CCRC-32 与 LFSR 在 C 中逐字节
【发布时间】:2015-03-26 14:41:23
【问题描述】:

我在 C 中实现了一个 CRC32 算法,但经过数小时的环顾并尝试修复它,它仍然无法正常工作。它可以编译,但校验和与几个在线 CRC 计算器中的不同。我怀疑错误出现在“if (0 != (character & j))”这一行,但不明白,因为它甚至与维基百科上的代码基本相同。

wikipedia

int CRC32_C(char *message){
    int length, i, j;
    unsigned long p,g;
    char character;
    p = 0x00000000;
    g = 0x04C11DB7;
    length = strlen(message);

    for (i = 0; i < length; i++){
        character=*message;
        //iterieren durch die bits jedes zeichens
        for (j= 0x80; j != 0; j >>= 1){ 
            //(p & 0x80000000)? 1 : 0)
            if (0 != (character & j))
                p = (p << 1) ^ g;
            else
                p <<=1;
        }
        message++;
    }
    return p;
}
//sample main
int main(char ** argv, int argc){
    char *msg;
    int p;
    msg = "HALLO";
    p = CRC32_C(msg);
    printf("p ist 0x%x \n", p);
    return 0;
}

示例输入:“HALLO”

预期结果:0x4E26F361(根据this page,使用相同的生成多项式,如页面底部所示)

实际结果:0xc25a747d

@chux:我尝试删除 if 子句中的“0 !=”,但并没有改变结果。

CRC32_C 仅代表“在 C 中实现”。正如生成多项式所暗示的,它是标准以太网。

感谢您的帮助

【问题讨论】:

  • 你在看维基百科的哪个代码?
  • length 是一个未初始化的变量
  • @Nayuki Minase lengthlength = strlen(message); 一起显示 OK
  • 请发布示例输入、错误输出和预期输出。
  • 建议if (character &amp; j) p ^= g; p &lt;&lt;=1; 而不是if (0 != (character &amp; j)) p = (p &lt;&lt; 1) ^ g; else p &lt;&lt;=1;

标签: c semantics crc32


【解决方案1】:

CRC 可能是 msb 到 lsb 或 lsb 到 msb,生成多项式在网上的例子中可能不同。 CRC32_F 是 msb 到 lsb,CRC32_R 是 lsb 到 msb(多项式反转)。如果你能找到一个使用十六进制的在线 CRC 计算器,请尝试使用 hex 01 来测试 msb 到 lsb,或使用 hex 80 来测试 lsb 到 msb。其他变体将 crc 初始化为 0xffffffff 和/或在计算 crc 后反转(不)crc。看一个ethernet crc的描述,尝试使用CRC32_R,但是将crc的初始化改为crc = 0xfffffffful; .

unsigned long CRC32_F(unsigned char *message, size_t length){
    size_t i, j;
    unsigned long crc,gnp;
    crc = 0x00000000ul;
    gnp = 0x04C11DB7ul;
    for (i = 0; i < length; i++){
        crc ^= ((unsigned long)*message)<<24;
        for (j = 0; j < 8; j++){ 
            if (crc & 0x80000000ul)
                crc = (crc << 1) ^ gnp;
            else
                crc = (crc << 1);
        }
        message++;
    }
    return crc;
}

unsigned long CRC32_R(unsigned char *message, size_t length){
    size_t i, j;
    unsigned long crc,gnp;
    crc = 0x00000000ul;
    gnp = 0xEDB88320ul;
    for (i = 0; i < length; i++){
        crc ^= ((unsigned long)*message)<<0;
        for (j = 0; j < 8; j++){ 
            if (crc & 0x00000001ul)
                crc = (crc >> 1) ^ gnp;
            else
                crc = (crc >> 1);
        }
        message++;
    }
    return crc;
}

【讨论】:

  • 很好,这个答案使用的是unsigned char,而不是char。虽然j 可能只是intunsigned
【解决方案2】:

这将从 HALLO 生成 CRC 0x4E26F361

#include <stddef.h>
#include <stdint.h>

/* CRC-32 (Ethernet, ZIP, etc.) polynomial in reversed bit order. */
#define POLY 0xedb88320


/* Compute CRC of buf[0..len-1] with initial CRC of crc.  Start
   with crc == 0. */
uint32_t crc32c(uint32_t crc, const unsigned char *buf, size_t len)
{
    int k;

    crc = ~crc;
    while (len--) {
        crc ^= *buf++;
        for (k = 0; k < 8; k++)
            crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
    }
    return ~crc;
}

上面是逐位计算 CRC,其中有更快的方法。这恰好是常用的 CRC,因此您可以在 zlib 中找到一个快速实现,称为 crc32(),它已经作为大多数系统中的已安装库提供。

【讨论】:

    猜你喜欢
    • 2014-11-20
    • 1970-01-01
    • 2016-03-12
    • 2011-06-30
    • 2014-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多