CRC 16, C to C#

  • 本文关键字:to CRC c# c crc crc16
  • 更新时间 :
  • 英文 :


我有CRC-16计算的代码示例,我想将其转换为C#。它必须保持相同的逻辑,因为它可以与其他机器一起工作。

我看到了从c到c的crc16,但它不起作用(结果不同(,可能是因为变量类型的原因。

原始代码为:输入字符="A",余数=0,输出=390

#define CRC_POLYNOMIAL 0x8005 /* CRC polynomial */
short Calculate_CRC ( char ch, short remainder ){
char *ch_ptr;
int i;
// the different part
ch_ptr = (char*)&remainder;
*(ch_ptr+1) = *(ch_ptr+1) ^ ch; /* exclusive or ch with msb of remainder */
for (i=0; i<=7; i++)
if (remainder < 0)
{ /* msb of remainder = 1 */
remainder = remainder << 1;
remainder = remainder ^ CRC_POLYNOMIAL;
}
else
remainder = remainder << 1;
return (remainder);
}

我的代码是:输入字符="A",余数=0,输出=514

static public ushort func(byte ch, ushort remainder, int f) {
// the different part
byte[] rawCrc = new byte[2];
rawCrc[0] = (byte)(remainder & 0x00FF);
rawCrc[1] = (byte)((remainder >> 8) & 0x00FF);
rawCrc[0] ^= ch;
remainder &= (byte)(rawCrc[0]);
for (int i = 0; i <= 7; i++)
if ((remainder & (0x8000)) == 0) { /* msb of remainder = 1 */
remainder <<= 1;
remainder ^= POL;
}
else
remainder <<= 1;
return remainder;
}

结果是不同的,但正如我所看到的,我的代码仍然根据需要使用msb执行xor。

我该怎么修?

TIA-

您的C#代码与您的C代码不等价。具体来说:

rawCrc[0] ^= ch;

。。。将chremainder最低有效字节异或,而C代码中的相应操作是与最高无效字节异或。

此外,这个C#行:

remainder &= (byte)(rawCrc[0]);

。。。似乎与C代码中的任何内容都不对应,而且从表面上看是错误的。我想你的意思是将两个字节重新组合成remainder,但这并不能做到。我建议完全不使用rawCrc,而是使用之类的方法

remainder = remainder ^ ((ch & 0xff) << 8);

此外,这个C#if语句中的测试:

if ((remainder & (0x8000)) == 0) { /* msb of remainder = 1 */

。。。相对于C代码中的相应测试是相反的,并且与后面注释断言的含义不一致。

试试这个。。。它应该(应该(等同于C版本。请注意,我删除了byte[]阵列。

const short CRC_POLYNOMIAL = unchecked((short)0x8005);
static short Calculate_CRC(byte ch, short remainder)
{
short ch_ptr = (short)(remainder & 0xFF);
ch_ptr |= (short)((remainder & 0xFF00) ^ (ch << 8));
// You could directly use ch_ptr from now on!
remainder = ch_ptr;
for (int i = 0; i <= 7; i++)
{
if (remainder < 0)
{ /* msb of remainder = 1 */
remainder = (short)(remainder << 1);
remainder = (short)(remainder ^ CRC_POLYNOMIAL);
}
else
{
remainder = (short)(remainder << 1);
}
}
return remainder;
}

请注意,我通常会删除short并将其更改为ushort。一想到某件东西中有一个小符号,应该被视为小符号,我就想吐。

const ushort CRC_POLYNOMIAL = (ushort)0x8005;
static ushort Calculate_CRC(byte ch, ushort remainder)
{
ushort remainder2 = (ushort)(remainder & 0xFF);
remainder2 |= (ushort)((remainder & 0xFF00) ^ (ch << 8));
for (int i = 0; i <= 7; i++)
{
if (remainder2 > short.MaxValue)
{ /* msb of remainder = 1 */
remainder2 = (ushort)(remainder2 << 1);
remainder2 = (ushort)(remainder2 ^ CRC_POLYNOMIAL);
}
else
{
remainder2 = (ushort)(remainder2 << 1);
}
}
return remainder2;
}

C代码中的这一行:*(ch_ptr+1) = *(ch_ptr+1) ^ ch;ch排他到remainder字节上。这是一种可怕的方法,因为在大型endian机器上会失败。在C中,他们应该做的是remainder ^= (short)ch << 8;。这将是可移植的,读者也会更清楚地看到正在发生的事情。这就是我在下面的C#代码中所做的,并为C#进行了适当的选角(它似乎有非常奇怪的隐含推广规则(:

static ushort Calculate_CRC(byte ch, ushort crc) {
crc ^= (ushort)(ch << 8);
for (int i = 0; i < 8; i++)
crc = (ushort)((crc & 0x8000) == 0 ? crc << 1 : (crc << 1) ^ 0x8005);
return crc;
}

最新更新