C的确定CRC

由于CRC被如此广泛地使用,我很惊讶在C中很难找到CRC实现。

对于C,是否存在“确定的”CRC计算片段/算法,“每个人”都使用? 或者:是否有一个很好的CRC实现,有人可以保证,并指向我? 我正在寻找CRC8和CRC16实现。

想想看,我的情况可能有点不同寻常。 我正在为Linux编写C代码,代码最终应该移植到微控制器上。 似乎有些微控制器API确实带有CRC实现; 无论如何,我正在寻找一个通用的软件实现(我读到CRC原本是硬件实现的)。

没有。没有“确定的CRC”,因为CRC代表一组基于多项式的算法。 通常基于大小给出各种[模糊的]通用名称(例如CRC-8,CRC-32)。 不幸的是,大多数尺寸有几种不同的版本。

维基百科的循环冗余检查条目列出了一些常见的变体,但必须使用给定域正确校验和 ,否则将存在不兼容性。 (请参阅我对Mike的回答,以了解这可能有多混乱!)

无论如何,选择一个合适的实现并使用它 – 不缺少可以在网上找到的例子。 如果碰巧有一个提供合适实现的库,那么,无论如何都要使用它。 但是,没有“标准”C库。

以下是一些资源:

  • AutomationWiki上的“CRC16”(CRC-16-CCITT)实现。
  • 对Dobbs博士实施CCITT周期性冗余检查 。
  • Chris Borrelli撰写的IEEE 802.3 Cyclic Redundancy Check文章讨论了生成Verilog(即“到硬件”)实现的过时Xilinx工具。
  • 请参阅相关问题CRC32 C或C ++实现 – 请注意,某些答案与“CRC32”(IEEE 802.3)和其他与Adler-32相关 。
  • librock库, boost ,来自GNU core utils的cksum源代码。

在C中找到CRC实现应该不难。您可以在zlib中找到相对复杂的CRC-32实现。

以下是几个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  // 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  #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 

不确定CRC-8或CRC-16,但RFC 1952中有CRC-32代码示例。 该RFC还引用了V.42标准,该标准在8.1.1.6节中描述了CRC-16。

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的两个最低有效字节即可。)

有许多不同的算法用于实现CRC。 有一个天真的多项式除法。

以下是用于通用32位CRC计算的各种算法的链接,在C中。 作者还给出了一些速度比较。

Koopman有一个网站,提供各种CRC的性能,以及给定数据包长度的最佳CRC的指南。