在 C 中更新 CRC32 值
Updating CRC32 Value in C
我参考了 hackersdelight 的 CRC32 实现,我刚刚从那里编辑了 crc32h
函数并使其获取一个字节并更新最后一个 CRC32 值。因为我需要用新的 byte
输入计算新的 CRC32 值。我可以通过向它发送一个数组来让它工作,因为在调用 CRC32 函数之前我不能将我的整个保存到数组中。所以我想更新为前一个字节计算的最后一个 CRC32 值。下面是 hackersdelight 的实现:
unsigned int crc32h(unsigned char *message) {
int i, crc;
unsigned int byte, c;
const unsigned int g0 = 0xEDB88320, g1 = g0>>1,
g2 = g0>>2, g3 = g0>>3, g4 = g0>>4, g5 = g0>>5,
g6 = (g0>>6)^g0, g7 = ((g0>>6)^g0)>>1;
i = 0;
crc = 0xFFFFFFFF;
while ((byte = message[i]) != 0) { // Get next byte.
crc = crc ^ byte;
c = ((crc<<31>>31) & g7) ^ ((crc<<30>>31) & g6) ^
((crc<<29>>31) & g5) ^ ((crc<<28>>31) & g4) ^
((crc<<27>>31) & g3) ^ ((crc<<26>>31) & g2) ^
((crc<<25>>31) & g1) ^ ((crc<<24>>31) & g0);
crc = ((unsigned)crc >> 8) ^ c;
i = i + 1;
}
return ~crc;
}
下面是我编辑的功能
unsigned int crc32h(uint8_t byte,int crc) {
unsigned int c;
const unsigned int g0 = 0xEDB88320, g1 = g0>>1,
g2 = g0>>2, g3 = g0>>3, g4 = g0>>4, g5 = g0>>5,
g6 = (g0>>6)^g0, g7 = ((g0>>6)^g0)>>1;
crc = crc ^ byte;
c = ((crc<<31>>31) & g7) ^ ((crc<<30>>31) & g6) ^
((crc<<29>>31) & g5) ^ ((crc<<28>>31) & g4) ^
((crc<<27>>31) & g3) ^ ((crc<<26>>31) & g2) ^
((crc<<25>>31) & g1) ^ ((crc<<24>>31) & g0);
crc = ((unsigned)crc >> 8) ^ c;
crc = ~crc;
return crc;
}
如果我发送一个字节和 default CRC value (0xFFFFFFFF)
,此代码会成功计算 CRC32 值。但是我无法更新CRC,例如:
int crc = 0xFFFFFFFF;
crc = crc32h(0x11,crc); //This gives me the correct CRC32 for `0x11`
crc = crc32h(0x22,crc); //But this does not give me the correct CRC32 for `0x1122`
为什么它不更新关于以前的 CRC 值的新 CRC 值?
区别在于第一个函数只反转一次CRC,
在消化所有字节之后,而您编辑的函数将反转
处理每个字节后的 CRC。
一个可能的解决方案是在
输入函数:
unsigned int crc32h(uint8_t byte,int crc) {
unsigned int c;
const unsigned int g0 = 0xEDB88320, g1 = g0>>1,
g2 = g0>>2, g3 = g0>>3, g4 = g0>>4, g5 = g0>>5,
g6 = (g0>>6)^g0, g7 = ((g0>>6)^g0)>>1;
crc = ~crc; // <--- ADDED
crc = crc ^ byte;
c = ((crc<<31>>31) & g7) ^ ((crc<<30>>31) & g6) ^
((crc<<29>>31) & g5) ^ ((crc<<28>>31) & g4) ^
((crc<<27>>31) & g3) ^ ((crc<<26>>31) & g2) ^
((crc<<25>>31) & g1) ^ ((crc<<24>>31) & g0);
crc = ((unsigned)crc >> 8) ^ c;
crc = ~crc;
return crc;
}
并从 0x0 而不是 0xFFFFFFFF 开始:
int crc = 0;
crc = crc32h(0x11,crc);
crc = crc32h(0x22,crc);
我参考了 hackersdelight 的 CRC32 实现,我刚刚从那里编辑了 crc32h
函数并使其获取一个字节并更新最后一个 CRC32 值。因为我需要用新的 byte
输入计算新的 CRC32 值。我可以通过向它发送一个数组来让它工作,因为在调用 CRC32 函数之前我不能将我的整个保存到数组中。所以我想更新为前一个字节计算的最后一个 CRC32 值。下面是 hackersdelight 的实现:
unsigned int crc32h(unsigned char *message) {
int i, crc;
unsigned int byte, c;
const unsigned int g0 = 0xEDB88320, g1 = g0>>1,
g2 = g0>>2, g3 = g0>>3, g4 = g0>>4, g5 = g0>>5,
g6 = (g0>>6)^g0, g7 = ((g0>>6)^g0)>>1;
i = 0;
crc = 0xFFFFFFFF;
while ((byte = message[i]) != 0) { // Get next byte.
crc = crc ^ byte;
c = ((crc<<31>>31) & g7) ^ ((crc<<30>>31) & g6) ^
((crc<<29>>31) & g5) ^ ((crc<<28>>31) & g4) ^
((crc<<27>>31) & g3) ^ ((crc<<26>>31) & g2) ^
((crc<<25>>31) & g1) ^ ((crc<<24>>31) & g0);
crc = ((unsigned)crc >> 8) ^ c;
i = i + 1;
}
return ~crc;
}
下面是我编辑的功能
unsigned int crc32h(uint8_t byte,int crc) {
unsigned int c;
const unsigned int g0 = 0xEDB88320, g1 = g0>>1,
g2 = g0>>2, g3 = g0>>3, g4 = g0>>4, g5 = g0>>5,
g6 = (g0>>6)^g0, g7 = ((g0>>6)^g0)>>1;
crc = crc ^ byte;
c = ((crc<<31>>31) & g7) ^ ((crc<<30>>31) & g6) ^
((crc<<29>>31) & g5) ^ ((crc<<28>>31) & g4) ^
((crc<<27>>31) & g3) ^ ((crc<<26>>31) & g2) ^
((crc<<25>>31) & g1) ^ ((crc<<24>>31) & g0);
crc = ((unsigned)crc >> 8) ^ c;
crc = ~crc;
return crc;
}
如果我发送一个字节和 default CRC value (0xFFFFFFFF)
,此代码会成功计算 CRC32 值。但是我无法更新CRC,例如:
int crc = 0xFFFFFFFF;
crc = crc32h(0x11,crc); //This gives me the correct CRC32 for `0x11`
crc = crc32h(0x22,crc); //But this does not give me the correct CRC32 for `0x1122`
为什么它不更新关于以前的 CRC 值的新 CRC 值?
区别在于第一个函数只反转一次CRC, 在消化所有字节之后,而您编辑的函数将反转 处理每个字节后的 CRC。
一个可能的解决方案是在 输入函数:
unsigned int crc32h(uint8_t byte,int crc) {
unsigned int c;
const unsigned int g0 = 0xEDB88320, g1 = g0>>1,
g2 = g0>>2, g3 = g0>>3, g4 = g0>>4, g5 = g0>>5,
g6 = (g0>>6)^g0, g7 = ((g0>>6)^g0)>>1;
crc = ~crc; // <--- ADDED
crc = crc ^ byte;
c = ((crc<<31>>31) & g7) ^ ((crc<<30>>31) & g6) ^
((crc<<29>>31) & g5) ^ ((crc<<28>>31) & g4) ^
((crc<<27>>31) & g3) ^ ((crc<<26>>31) & g2) ^
((crc<<25>>31) & g1) ^ ((crc<<24>>31) & g0);
crc = ((unsigned)crc >> 8) ^ c;
crc = ~crc;
return crc;
}
并从 0x0 而不是 0xFFFFFFFF 开始:
int crc = 0;
crc = crc32h(0x11,crc);
crc = crc32h(0x22,crc);