2013-03-02 20 views
16

Dal momento che CRC è così ampiamente usato, sono sorpreso da avere difficoltà a trovare le implementazioni CRC in C.definitiva CRC per C

Esiste un "definitivo" calcolo CRC frammento/algoritmo per C, che "tutti "usa? Oppure: esiste una buona implementazione CRC per cui qualcuno possa garantire e indicarmi? Sto cercando in particolare le implementazioni CRC8 e CRC16.

Vieni a pensarci, la mia situazione potrebbe essere un po 'non convenzionale. Sto scrivendo il codice C per Linux e il codice dovrebbe essere portato su un microcontrollore. Sembra che alcune API di microcontrollori abbiano implementazioni CRC; in ogni caso, sto cercando un'implementazione software generica (ho letto che CRC è originariamente pensato per essere implementato hardware).

risposta

14

No. Non esiste un "CRC definitivo" poiché CRC rappresenta un insieme di algoritmi basati su polinomi. Vari nomi comuni [ambigui] vengono solitamente forniti in base alla dimensione (ad esempio CRC-8, CRC-32). Sfortunatamente, ci sono diverse versioni per la maggior parte delle dimensioni. ingresso

di Wikipedia Cyclic Redundancy Check elenca alcune varianti comuni, ma la corretto checksum per la dato dominio deve essere utilizzato, altrimenti non ci sarà incompatibilità. (Vedi il mio commento alla risposta di Mike per quanto possa essere confuso!)

In ogni caso, scegli un'implementazione adatta e usalo - non mancano esempi che possono essere trovati online. Se capita che ci sia una libreria che fornisce un'implementazione adatta allora, con tutti i mezzi, usala. Tuttavia, non esiste una libreria C "standard" per questo.

Ecco alcune risorse:

+3

+1. Un altro buon (vecchio) riassunto degli algoritmi CRC [qui] (http://www.ross.net/crc/download/crc_v3.txt). –

2

Non sei sicuro di CRC-8 o CRC-16, ma non v'è esempio di codice CRC-32 in RFC 1952. Questo RFC fa anche riferimento allo standard V.42, che descrive un CRC-16 nella sezione 8.1.1.6.

RFC 1952 afferma anche:

 If FHCRC is set, a CRC16 for the gzip header is present, 
     immediately before the compressed data. The CRC16 consists 
     of the two least significant bytes of the CRC32 for all 
     bytes of the gzip header up to and not including the CRC16. 
     [The FHCRC bit was never set by versions of gzip up to 
     1.2.4, even though it was documented with a different 
     meaning in gzip 1.2.4.] 

Quindi c'è la vostra CRC-16 e CRC-32, potenzialmente. (prendi semplicemente i due byte meno significativi del CRC-32, ovvero.)

+1

Nit: GZip (e V.42 et al) usano CRC-32 IEEE 802.3 per "CRC32". Tuttavia, "metà" di un CRC-32 è * non * un CRC-16 anche se è chiamato "CRC16" in quanto rappresenta solo un checksum a 16 bit. CRC-16-CCITT è un esempio di un vero CRC-16. –

+0

@Nit Tranne CRC-16-CCITT è al massimo un CRC a 16 bit mediocre. L'unico motivo per raccomandarlo è che esistono implementazioni che è possibile copiare e incollare. – Flip

27

Non dovrebbe essere difficile trovare implementazioni CRC in C. È possibile trovare un'implementazione relativamente sofisticata di CRC-32 in zlib.

Queste sono le definizioni per diversi 16-bit e 8-bit CRCs, che utilizzano le convenzioni in questo excellent introduction to CRCs.

Ecco una semplice implementazione di un CRC-8:

// 8-bit CRC using the polynomial x^8+x^6+x^3+x^2+1, 0x14D. 
// Chosen based on Koopman, et al. (0xA6 in his notation = 0x14D >> 1): 
// http://www.ece.cmu.edu/~koopman/roses/dsn04/koopman04_crc_poly_embedded.pdf 
// 
// This implementation is reflected, processing the least-significant bit of the 
// input first, has an initial CRC register value of 0xff, and exclusive-or's 
// the final register value with 0xff. As a result the CRC of an empty string, 
// and therefore the initial CRC value, is zero. 
// 
// The standard description of this CRC is: 
// width=8 poly=0x4d init=0xff refin=true refout=true xorout=0xff check=0xd8 
// name="CRC-8/KOOP" 

static unsigned char const crc8_table[] = { 
    0xea, 0xd4, 0x96, 0xa8, 0x12, 0x2c, 0x6e, 0x50, 0x7f, 0x41, 0x03, 0x3d, 
    0x87, 0xb9, 0xfb, 0xc5, 0xa5, 0x9b, 0xd9, 0xe7, 0x5d, 0x63, 0x21, 0x1f, 
    0x30, 0x0e, 0x4c, 0x72, 0xc8, 0xf6, 0xb4, 0x8a, 0x74, 0x4a, 0x08, 0x36, 
    0x8c, 0xb2, 0xf0, 0xce, 0xe1, 0xdf, 0x9d, 0xa3, 0x19, 0x27, 0x65, 0x5b, 
    0x3b, 0x05, 0x47, 0x79, 0xc3, 0xfd, 0xbf, 0x81, 0xae, 0x90, 0xd2, 0xec, 
    0x56, 0x68, 0x2a, 0x14, 0xb3, 0x8d, 0xcf, 0xf1, 0x4b, 0x75, 0x37, 0x09, 
    0x26, 0x18, 0x5a, 0x64, 0xde, 0xe0, 0xa2, 0x9c, 0xfc, 0xc2, 0x80, 0xbe, 
    0x04, 0x3a, 0x78, 0x46, 0x69, 0x57, 0x15, 0x2b, 0x91, 0xaf, 0xed, 0xd3, 
    0x2d, 0x13, 0x51, 0x6f, 0xd5, 0xeb, 0xa9, 0x97, 0xb8, 0x86, 0xc4, 0xfa, 
    0x40, 0x7e, 0x3c, 0x02, 0x62, 0x5c, 0x1e, 0x20, 0x9a, 0xa4, 0xe6, 0xd8, 
    0xf7, 0xc9, 0x8b, 0xb5, 0x0f, 0x31, 0x73, 0x4d, 0x58, 0x66, 0x24, 0x1a, 
    0xa0, 0x9e, 0xdc, 0xe2, 0xcd, 0xf3, 0xb1, 0x8f, 0x35, 0x0b, 0x49, 0x77, 
    0x17, 0x29, 0x6b, 0x55, 0xef, 0xd1, 0x93, 0xad, 0x82, 0xbc, 0xfe, 0xc0, 
    0x7a, 0x44, 0x06, 0x38, 0xc6, 0xf8, 0xba, 0x84, 0x3e, 0x00, 0x42, 0x7c, 
    0x53, 0x6d, 0x2f, 0x11, 0xab, 0x95, 0xd7, 0xe9, 0x89, 0xb7, 0xf5, 0xcb, 
    0x71, 0x4f, 0x0d, 0x33, 0x1c, 0x22, 0x60, 0x5e, 0xe4, 0xda, 0x98, 0xa6, 
    0x01, 0x3f, 0x7d, 0x43, 0xf9, 0xc7, 0x85, 0xbb, 0x94, 0xaa, 0xe8, 0xd6, 
    0x6c, 0x52, 0x10, 0x2e, 0x4e, 0x70, 0x32, 0x0c, 0xb6, 0x88, 0xca, 0xf4, 
    0xdb, 0xe5, 0xa7, 0x99, 0x23, 0x1d, 0x5f, 0x61, 0x9f, 0xa1, 0xe3, 0xdd, 
    0x67, 0x59, 0x1b, 0x25, 0x0a, 0x34, 0x76, 0x48, 0xf2, 0xcc, 0x8e, 0xb0, 
    0xd0, 0xee, 0xac, 0x92, 0x28, 0x16, 0x54, 0x6a, 0x45, 0x7b, 0x39, 0x07, 
    0xbd, 0x83, 0xc1, 0xff}; 

#include <stddef.h> 

// Return the CRC-8 of data[0..len-1] applied to the seed crc. This permits the 
// calculation of a CRC a chunk at a time, using the previously returned value 
// for the next seed. If data is NULL, then return the initial seed. See the 
// test code for an example of the proper usage. 
unsigned crc8(unsigned crc, unsigned char const *data, size_t len) 
{ 
    if (data == NULL) 
     return 0; 
    crc &= 0xff; 
    unsigned char const *end = data + len; 
    while (data < end) 
     crc = crc8_table[crc^*data++]; 
    return crc; 
} 

// crc8_slow() is an equivalent bit-wise implementation of crc8() that does not 
// need a table, and which can be used to generate crc8_table[]. Entry k in the 
// table is the CRC-8 of the single byte k, with an initial crc value of zero. 
// 0xb2 is the bit reflection of 0x4d, the polynomial coefficients below x^8. 
unsigned crc8_slow(unsigned crc, unsigned char const *data, size_t len) 
{ 
    if (data == NULL) 
     return 0; 
    crc = ~crc & 0xff; 
    while (len--) { 
     crc ^= *data++; 
     for (unsigned k = 0; k < 8; k++) 
      crc = crc & 1 ? (crc >> 1)^0xb2 : crc >> 1; 
    } 
    return crc^0xff; 
} 

#ifdef TEST 
#include <stdio.h> 
#define CHUNK 16384 

int main(void) { 
    unsigned char buf[CHUNK]; 
    unsigned crc = crc8(0, NULL, 0); 
    size_t len; 
    do { 
     len = fread(buf, 1, CHUNK, stdin); 
     crc = crc8(crc, buf, len); 
    } while (len == CHUNK); 
    printf("%#02x\n", crc); 
    return 0; 
} 
#endif 
+1

+1 per il bel codice semplice e pulito che può essere utile per varie esigenze e progetti su cui sto lavorando. Il come per l'invenzione di Adler-32 ?? Beh, non posso darlo più di +1, quindi ... :) Non ho scoperto chi fosse l'autore fino a quando non ho fatto scorrere verso il basso per vedere cosa avevano detto gli altri! heh ... Ma seriamente, grazie Mark, per il bel CRC8. Ora è nella mia "Collezione" CRC se vuoi. :) – LarryF

1

Esistono diversi algoritmi utilizzati per implementare CRC. C'è l'ingenuo che fa la divisione polinomiale.

Here è un collegamento per vari algoritmi, in C, per calcoli CRC generici a 32 bit. L'autore offre anche alcuni confronti di velocità.

Koopman dispone di un sito Web che offre le prestazioni di vari CRC, nonché una guida ai migliori CRC per una determinata lunghezza del pacchetto.

Problemi correlati