如何修改CRC32代码中的多项式以匹配cksum计算结果?
解决CRC32与cksum结果一致的问题
你的代码要匹配cksum的CRC结果,需要修正几个关键参数和逻辑,以下是具体修改方案:
关键问题分析
- 变量类型错误:用
int存储CRC会导致有符号数移位时的符号扩展错误,必须用无符号32位类型uint32_t。 - 初始值错误:cksum的CRC初始值为
0xFFFFFFFF,而非你的代码中的0。 - 多项式不匹配:你的代码是LSB优先的表驱动实现,而标准CRC32(cksum使用的)是MSB优先,因此需要使用反转后的多项式
0xEDB88320(原多项式0x04C11DB7的位反转结果)。 - 未处理文件长度:cksum会将文件的字节数(以32位大端整数形式)追加到数据末尾参与CRC计算,这是你之前忽略的核心步骤。
- 字节序反转:cksum输出的CRC是大端字节序,而内存中计算出的是小端,需要最后反转字节顺序。
修改后的代码
#include <stdio.h> #include <stdlib.h> #include <stdint.h> int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "usage: %s <file>\n", argv[0]); exit(EXIT_FAILURE); } FILE *f = fopen(argv[1], "rb"); if (f == NULL) { perror("fopen()"); exit(EXIT_FAILURE); } uint32_t crc_table[256]; const uint32_t POLY = 0xEDB88320; // CRC32反转多项式,适配LSB优先计算 // 生成CRC表 for (int i = 0; i < 256; i++) { uint32_t crc = i; for (int j = 0; j < 8; j++) { crc = (crc & 1) ? ((crc >> 1) ^ POLY) : (crc >> 1); } crc_table[i] = crc; } uint32_t crc = 0xFFFFFFFF; // 初始值匹配cksum uint64_t size = 0; int c; // 处理文件内容 while ((c = fgetc(f)) != EOF) { size++; crc = crc_table[(crc ^ c) & 0xFF] ^ (crc >> 8); } // 处理文件长度(cksum要求将长度以32位大端加入计算) for (int i = 3; i >= 0; i--) { uint8_t len_byte = (size >> (i * 8)) & 0xFF; crc = crc_table[(crc ^ len_byte) & 0xFF] ^ (crc >> 8); } crc ^= 0xFFFFFFFF; // 最终异或 // 反转字节序,匹配cksum的大端输出 crc = ((crc >> 24) & 0xFF) | ((crc >> 8) & 0xFF00) | ((crc << 8) & 0xFF0000) | ((crc << 24) & 0xFF000000); printf("%u\n", crc); fclose(f); return 0; }
验证方式
编译修改后的代码,对同一文件分别运行你的程序和cksum命令,对比输出的CRC值(cksum输出的第一个数就是CRC值):
gcc crc_cksum.c -o crc_cksum ./crc_cksum test.txt cksum test.txt
内容的提问来源于stack exchange,提问作者sokol
相关产品推荐
相关产品推荐

