codigo - CRC definitivo para C
crc en c++ (4)
Hay varios algoritmos diferentes utilizados para implementar los CRC. Ahí está el ingenuo que hace la división polinomial.
Here hay un enlace para varios algoritmos, en C, para cálculos CRC genéricos de 32 bits. El autor también da algunas comparaciones de velocidad.
Koopman tiene un sitio web que ofrece los resultados de varios CRC, así como una guía de los mejores CRC para una longitud de paquete determinada.
Dado que el CRC se usa tanto, me sorprende que me cuesta mucho encontrar las implementaciones del CRC en C.
¿Hay un fragmento / algoritmo de cálculo de CRC "definitivo" para C, que utiliza "todos"? O bien: ¿hay una buena implementación de CRC por la que alguien pueda responder y señalarme? Estoy buscando implementaciones CRC8 y CRC16 en particular.
Ahora que lo pienso, mi situación puede ser un poco poco convencional. Estoy escribiendo el código C para Linux, y el código debería eventualmente ser transferido a un microcontrolador. Parece que algunas API de microcontroladores vienen con implementaciones CRC; En cualquier caso, estoy buscando una implementación de software genérica (leí que CRC originalmente debe implementarse en hardware).
No debería ser difícil encontrar implementaciones de CRC en C. Puede encontrar una implementación relativamente sofisticada de CRC-32 en zlib .
Aquí hay definiciones de varios CRC de 16-bit y 8 bits , que utilizan las convenciones en esta here .
Aquí hay una implementación simple de 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
No estoy seguro acerca de CRC-8 o CRC-16, pero hay un código de ejemplo CRC-32 en RFC 1952 . Este RFC también hace referencia al estándar V.42 , que describe un CRC-16 en la sección 8.1.1.6.
RFC 1952 también establece:
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.]
Así que hay su CRC-16 y CRC-32, potencialmente. (solo tome los dos bytes menos significativos del CRC-32, es decir)
No. No hay "CRC definitivo", ya que CRC representa un conjunto de algoritmos basados en polinomios. Generalmente se dan varios nombres comunes [ambiguos] según el tamaño (por ejemplo, CRC-8, CRC-32). Desafortunadamente, hay varias versiones diferentes para la mayoría de los tamaños.
La entrada de la Revisión de redundancia cíclica de Wikipedia enumera algunas variantes comunes, pero se debe utilizar la suma de comprobación correcta para el dominio dado o, de lo contrario, habrá incompatibilidades. (¡Vea mi comentario a la respuesta de Mike para ver cuán confuso puede ser esto!)
De todos modos, elija una implementación adecuada y úsela, no hay escasez de ejemplos que se pueden encontrar en línea. Si resulta que hay una biblioteca que proporciona una implementación adecuada, entonces, por supuesto, úsala. Sin embargo, no existe una biblioteca C "estándar" para esto.
Aquí hay algunos recursos:
- Una implementación "CRC16" (CRC-16-CCITT) en AutomationWiki.
- Implementación del control de redundancia cíclica del CCITT en el Dr. Dobbs.
- El artículo sobre el control de redundancia cíclica IEEE 802.3 de Chris Borrelli analiza una herramienta obsoleta de Xilinx para generar implementaciones de Verilog (es decir, "al hardware").
- Consulte la pregunta relacionada CRC32 C o la implementación de C ++ : tenga en cuenta que algunas respuestas se relacionan con "CRC32" (IEEE 802.3) y otras con Adler-32 .
- La biblioteca de librock , boost , fuente de cksum de los utils principales de GNU ..