CRC-16算法的C语言实现(图文)

 先提供一些资料,本文使用的是CRC-16、CRC-CCITT或是任何自定义的CRC-16生成多项式

标准CRC生成多项式
名称 生成多项式              简记式   标准引用
CRC-4        x4+x+1                   0x3 ITU G.704   
CRC-8        x8+x5+x4+1              0x31                         
CRC-8        x8+x2+x1+1               0x07                         
CRC-8        x8+x6+x4+x3+x2+x1        0x5E     
CRC-12       x12+x11+x3+x+1           80F      
CRC-16       x16+x15+x2+1             0x8005 IBM SDLC    
CRC16-CCITT  x16+x12+x5+1             0x1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS    
CRC-32       x32+x26+x23+...+x2+x+1  0x04C11DB7  ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS    
CRC-32c      x32+x28+x27+...+x8+x6+1  0x1EDC6F41 SCTP

 先看一个CRC-16校验的例子了解CRC校验码是怎样生成的,待校验数据0xa743,此处使用的简记式为CRC-16 0x8005

以下就是我写的代码和流程图,代码在VC6.0环境下测试通过,不过由于scanf("%x",B)经过测试最多只能存4字节16进制数,所以,只有在N<=4的情况下正常,此问题正在寻找解决方案中。

#include<stdio.h>
#define N 4
#define U16_MSB(x)    ((x)&0x8000)
#define GEN_P    0x1021    //CRC-CCITT简记式,简记式中忽略最高位1,可换为CRC-16简记式0x8005或任意自定义简记式
#define MASK(x)    (1<<(x))  

typedef unsigned char uint8;
typedef unsigned short uint16;

main()
{
    uint8 B[N];
    uint8 i,j,cnt,temp_msb;
    uint16 temp;
    while(1)
    {
        cnt=0;
        scanf("%x",B);        //经测试,%x对应只能存32bit数据,小端存储,“高高低低”
        temp=B[N-1];
        temp=temp<<8;
        temp+=B[N-2];
        while(1)
        {
            if(cnt==N*8)                
                break;
            temp_msb=!!U16_MSB(temp);    //取两次反转化为布尔类型
            i=cnt%8;
            j=cnt/8;
            temp=temp<<1;
            cnt++;
            if((N-2-1-j)>=0 && B[N-2-1-j] & MASK(8-1-i))
                temp++;
            if(temp_msb)
                temp^=GEN_P;
        }
        printf("CRC:%#x
",temp);     
    }
}    

 要验证之前的例子,先将代码做一些修改,由于在编程之前就想到要适应不同的数据位数和生成多项式,这里的修改就很容易,只需修改宏定义,如下

#define N 2
#define GEN_P    0x8005

结果:

结果与之前分析的表格相符 此处高字节在前低字节在后

不过CRC应该是高字节在后低字节在前,这应该是很好改的。

原文地址:https://www.cnblogs.com/liutogo/p/3633426.html