CRC-32与LFSR字节Byte在C中

时间:2015-01-27 20:47:25

标签: c semantics crc32

我在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中实施”。正如Generator多项式所示,它是标准以太网。

感谢您的帮助

2 个答案:

答案 0 :(得分:3)

CRC可以是msb到lsb或lsb到msb,并且生成多项式在在线示例中可以是不同的。 CRC32_F是msb到lsb,CRC32_R是lsb到msb(多项式反转)。如果您可以找到一个取十六进制的在线CRC计算器,请尝试使用十六进制01来测试msb到lsb,或使用十六进制80来测试lsb到msb。其他变化在计算crc之后将crc初始化为0xffffffff和/或反转(而不是)crc。查看以太网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;
}

答案 1 :(得分:0)

这将从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()的快速实现,该实现在大多数系统中已作为已安装的库提供。