【发布时间】:2021-12-25 10:58:17
【问题描述】:
我正在遵循代码校正算法的无痛指南。 (https://zlib.net/crc_v3.txt) 我已经设法编写了一个 TABLE 算法,对增强部分使用额外的循环(我希望如此)。我正在尝试编写一个使用最广泛的 CRC32 版本(带有 0x04C11DB7 多项式),但我无法获得正确的 CRC 值。
我已经用提到的多项式获得了正确的 CRC32 值表。 我生成 CRC32 的代码(第 9 章和第 10 章):
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#define CRC32_BYTE_POSSIBLE_VALUES 255
#define CRC32_LAST_BIT_MASK 0x80000000
#define CRC32_POLYNOMIAL 0x04C11DB7
uint32_t __crc32_table[CRC32_BYTE_POSSIBLE_VALUES] = { 0 };
void __crc32_fill_crc_table() {
uint32_t reg;
uint8_t byte = 0;
for (;;) {
reg = (byte << 24);
for (uint8_t byte_size = 0; byte_size < 8; byte_size++) {
if (reg & CRC32_LAST_BIT_MASK) {
reg <<= 1;
reg ^= CRC32_POLYNOMIAL;
} else {
reg <<= 1;
}
}
__crc32_table[byte] = reg;
if (byte == 255)
break;
else
byte++;
}
}
void __crc32_print_table(uint32_t *arr) {
printf(" 0x%08X ", arr[0]);
for (uint32_t i = 1; i < 256; i++) {
if (!(i % 8))
printf("\n");
printf(" 0x%08X ", arr[i]);
}
printf("\n");
}
uint8_t inverse_byte(uint8_t byte) {
uint8_t reflected_byte = 0;
for (uint8_t i = 0; i < 8; i++) {
if (byte & (1 << i))
reflected_byte |= (1 << (7 - i));
}
return reflected_byte;
}
uint32_t inverse(uint32_t src) {
uint32_t toret;
for (uint8_t i = 0; i < 32; i++) {
if (src & (1 << i))
toret |= (1 << (31 - i));
}
return toret;
}
uint32_t __crc32_table_approach( unsigned char *data, size_t size) {
uint32_t reg = -1;
uint8_t top_byte;
for (size_t i = 0; i < size; i++) {
top_byte = (uint8_t)(reg >> 24);
reg = (reg << 8) | inverse_byte(data[i]);
reg ^= __crc32_table[top_byte];
}
for (size_t i = 0; i < 4; i++) {
top_byte = (uint8_t) (reg >> 24);
reg = (reg << 8) ;
reg ^= __crc32_table[top_byte];
}
return inverse(reg) ^ -1;
}
uint32_t calc_crc32(unsigned char *data, size_t size) {
if (!__crc32_table[1])
__crc32_fill_crc_table();
__crc32_print_table(__crc32_table);
return __crc32_table_approach(data, size);
}
int main( int argc, char** argv )
{
unsigned char* test = "123456789";
size_t test_len = strlen(test);
uint32_t crc = calc_crc32(test, test_len);
printf("CRC32: 0x%08X", crc);
return 0;
}
inverse函数反转UINT32值的位,函数inverse_byte反转UINT8值的位。
但是对于“123456789”字符串,我得到了错误的校验和。 有人可以帮助我吗?或者给点建议?
输入字符串:'123456789'
输出的 CRC:CRC32:0x22016B0A
所需的 CRC:CRC32:0xCBF43926
【问题讨论】:
-
编辑问题以提供minimal reproducible example,包括完整的可运行程序、重现问题的示例输入、观察到的输出和所需的输出。
-
添加了带有示例的存储库。
-
看起来指南说用
0初始化寄存器,而你用-1初始化它。你是故意的吗? -
据我所知,最广为人知的 CRC32 使用寄存器的初始值 0xFFFFFFFF,并且还通过最终的 XOR 反映输入/输出数据。本文档稍后会注明这些特征(REFIN/REFOUT 等)。
-
编辑问题以完全在问题内提供minimal reproducible example。外部链接可用于补充信息,但重现问题所需的所有信息(包括代码)都应包含在帖子本身内。 Stack Overflow 不是个人调试服务。它的存在是为了提供一个持久的问题和答案存储库,供其他人在未来使用。外部链接上的文件会随着时间的推移而改变或消失,因此不适合记录问题。