问题描述
我正在尝试创建一个函数,该函数采用单个字节并为给定的任何生成的多项式返回 CRC 值。
#include <stdio.h>
#include <stdint.h>
#define MSG_SIZE 7 // number of message bits
#define poly_SIZE 9 // number of gen. poly. bits
#define SHIFT_INPUT poly_SIZE-1 // zeros to be added to input
#define SHIFT_poly MSG_SIZE-1 // zeros to be added to polynomial
#define poly 0x11D // generated polynomial
#define poly_MSK (poly << SHIFT_poly) // add zeros to polynomial to be aligned with input
#define ALIGN_MSK (1 << (MSG_SIZE+poly_SIZE-2)) // for MSB_poly and MSB_input alignment check
uint64_t PartCRC(uint64_t input);
uint64_t PartCRC(uint64_t input){
input = ( input << SHIFT_INPUT );
for(int n = 0; n < MSG_SIZE; n++){
// if current (MSB) bit of input is "1"; if MSB_poly and MSB_input are aligned
if( input & ALIGN_MSK ){
input ^= poly_MSK; // input XOR poly
}
// if crc is calculated,don't shift
if( n == (MSG_SIZE-1) ) break;
input = ( input << 1 ); // shift input left each step
}
return (input >> SHIFT_poly); // return crc - trim zeros
}
void main(void) {
printf( "CRC for input: %llX\n",PartCRC(0x41) );
return;
}
除了从 PartCRC()
提供给 main()
函数的消息之外,我必须仅将生成的多项式定义为十六进制数加上其大小和消息大小(从 LSB 到 MSB 的位数)。
这个函数的作用是在每次迭代时将输入左移,在那里检查多项式的 MSB 和输入的 MSB 是否对齐;如果是这样,则在当前移位的输入和多项式之间执行按位 XOR
(即 poly_MSK
- poly
被移位以使其与当前移位的输入对齐)。最后,计算出的余数右移(因为它在 CRC 计算期间用零填充)。
我了解这个过程是如何工作的,我非常有信心它应该对每个 CRC 标准化生成的多项式正确运行,但是它只对少数非标准化多项式起作用。例如,它适用于 2.Introduction 段落(以及少数其他多项式)。
然而,对于其他(标准化的)多项式,它不起作用;在 this 站点检查代码的(非)有效性。在这里,我想指出,我了解关于生成的多项式计算 CRC 的方法很少 - 正态、逆向、倒数、逆倒数。为简单起见,我保持正常表示,并且在前面提到的站点要求已经计算的 CRC 时我也考虑了这一事实(我的意思是“初始值”和“最终 XOR 值”都是 0x00,虽然我不确定,那两个是什么意思)
解决方法
至少有一个潜在问题:整数大小
#define MSG_SIZE 7
#define POLY_SIZE 9
#define ALIGN_MSK (1 << (MSG_SIZE+POLY_SIZE-2))
当 MSG_SIZE+POLY_SIZE-2
超过 15 并且 1
是 16 位 int
时,这是一个问题。同样,对于 MSG_SIZE+POLY_SIZE-2
超过 31 并且 1
是 32 位 int
。
更好
#define ALIGN_MSK ((uint64_t)1 << (MSG_SIZE+POLY_SIZE-2))
以下类似问题。
#define POLY 0x11D
#define POLY_MSK (POLY << SHIFT_POLY)
input ^= POLY_MSK;
推荐
#define POLY_MSK ((uint64_t)POLY << SHIFT_POLY)
代码对 SHIFT_INPUT
的使用看起来不错,但推荐使用 ()
。
// #define SHIFT_INPUT POLY_SIZE-1
#define SHIFT_INPUT (POLY_SIZE-1)