Окончательный CRC для C - программирование
Подтвердить что ты не робот

Окончательный CRC для C

Поскольку CRC настолько широко используется, я удивлен тем, что трудно найти реализации CRC в C.

Есть ли "окончательный" фрагмент/алгоритм вычисления CRC для C, который использует "каждый"? Или: есть ли хорошая реализация CRC, за которую кто-то может ручаться и направить меня? Я ищу, в частности, реализации CRC8 и CRC16.

Подумайте об этом, моя ситуация может быть немного нетрадиционной. Я пишу код C для Linux, и в конечном итоге код должен быть перенесен на микроконтроллер. Кажется, что некоторые API-интерфейсы микроконтроллеров поставляются с реализациями CRC; в любом случае, я ищу универсальную программную реализацию (я читал, что CRC изначально предназначен для аппаратного обеспечения).

4b9b3361

Ответ 1

Нет. Не существует "окончательного CRC", поскольку CRC представляет собой набор алгоритмов, основанных на многочленах. Различные [неоднозначные] общие имена обычно даются на основе размера (например, CRC-8, CRC-32). К сожалению, для большинства размеров существует несколько разных версий.

Википедия Циклическая проверка избыточности содержит списки некоторых общих вариантов, но правильная контрольная сумма для данного домена должна использоваться, иначе будут несовместимы, (См. Мой комментарий к Майку, отвечайте за то, насколько это может быть запутано!)

В любом случае, выберите подходящую реализацию и используйте ее - нет недостатка в примерах, которые можно найти в Интернете. Если есть библиотека, которая обеспечивает подходящую реализацию, то, во что бы то ни стало, используйте это. Однако для этого нет "стандартной" библиотеки C.

Вот несколько ресурсов:

Ответ 2

Не сложно найти реализации CRC в C. Вы можете найти относительно сложную реализацию CRC-32 в zlib.

Ниже приведены определения для нескольких 16-бит и 8- бит CRC, которые используют соглашения в этом отличное введение в CRC.

Вот простая реализация 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

Ответ 3

Не уверен в CRC-8 или CRC-16, но есть пример кода CRC-32 в RFC 1952. Этот RFC также ссылается на стандарт V.42, который описывает CRC-16 в разделе 8.1.1.6.

RFC 1952 также заявляет:

        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.]

Таким образом, ваши CRC-16 и CRC-32 потенциально могут быть. (просто возьмите два младших байта CRC-32, то есть.)

Ответ 4

Существует множество различных алгоритмов, используемых для реализации CRC. Существует наивное, что делает полиномиальное деление.

Здесь - ссылка для различных алгоритмов в C для общих 32-битных вычислений CRC. Автор также дает некоторые сравнения скорости.

Koopman имеет сайт, дающий характеристики различных CRC, а также руководство по лучшим CRC для данной длины пакета.