Offset 变量在此算法中的重要性是什么?
What's the importance of the Offset variable in this algorithm?
这个算法中这个名为Offset的变量是什么意思?
它在第二个 calcCrc16 参数中声明。
对我来说它是无用的,因为它远离零并且用于总和。
此算法生成一个 crc-16。我试图理解这个算法,因为必须创建一个验证 crc-16 的算法,我想使用这个代码作为基础。
public sealed class CRC
{
private readonly int _polynom;
public static readonly CRC Default = new CRC(0xA001);
public CRC(int polynom)
{
_polynom = polynom;
}
public int CalcCrc16(byte[] buffer)
{
return CalcCrc16(buffer, 0, buffer.Length, _polynom, 0);
}
public static int CalcCrc16(byte[] buffer, int offset, int bufLen, int polynom, int preset)
{
preset &= 0xFFFF;
polynom &= 0xFFFF;
var crc = preset;
for (var i = 0; i < (bufLen + 2); i++)
{
var data = buffer[(i + offset) % buffer.Length] & 0xFF;
crc ^= data;
for (var j = 0; j < 8; j++)
{
if ((crc & 0x0001) != 0)
{
crc = (crc >> 1) ^ polynom;
}
else
{
crc = crc >> 1;
}
}
}
return crc & 0xFFFF;
}
}
它是 public
方法签名的一部分,适用于任何您想要计算 CRC 的情况,但不适用于整个缓冲区。
当然,大多数时候您可能只使用该方法的简单版本,在这种情况下参数始终为零,但通常散列和 CRC 实现是使用这样的 API 构建的,允许您根据需要分块计算 CRC。
我创建了一个简单的示例,使用一个 4 字节的小消息(在 6 字节的缓冲区中):
using System;
namespace crc16
{
class Program
{
private static ushort Crc16(byte[] bfr, int bfrlen)
{
ushort crc = 0;
for (int i = 0; i < bfrlen; i++)
{
crc ^= bfr[i];
for (int j = 0; j < 8; j++)
// assumes twos complement math
crc = (ushort)((crc >> 1)^((0 - (crc&1)) & 0xa001));
}
return crc;
}
static void Main(string[] args)
{
ushort crc;
byte[] data = new byte[6] {0x11, 0x22, 0x33, 0x44, 0x00, 0x00};
crc = Crc16(data, 4); // generate crc
data[4] = (byte)(crc & 0xff); // append crc (lsb first)
data[5] = (byte)(crc >> 8);
crc = Crc16(data, 6); // verify crc;
Console.WriteLine("{0:X4}", crc);
return;
}
}
}
这个算法中这个名为Offset的变量是什么意思? 它在第二个 calcCrc16 参数中声明。 对我来说它是无用的,因为它远离零并且用于总和。
此算法生成一个 crc-16。我试图理解这个算法,因为必须创建一个验证 crc-16 的算法,我想使用这个代码作为基础。
public sealed class CRC
{
private readonly int _polynom;
public static readonly CRC Default = new CRC(0xA001);
public CRC(int polynom)
{
_polynom = polynom;
}
public int CalcCrc16(byte[] buffer)
{
return CalcCrc16(buffer, 0, buffer.Length, _polynom, 0);
}
public static int CalcCrc16(byte[] buffer, int offset, int bufLen, int polynom, int preset)
{
preset &= 0xFFFF;
polynom &= 0xFFFF;
var crc = preset;
for (var i = 0; i < (bufLen + 2); i++)
{
var data = buffer[(i + offset) % buffer.Length] & 0xFF;
crc ^= data;
for (var j = 0; j < 8; j++)
{
if ((crc & 0x0001) != 0)
{
crc = (crc >> 1) ^ polynom;
}
else
{
crc = crc >> 1;
}
}
}
return crc & 0xFFFF;
}
}
它是 public
方法签名的一部分,适用于任何您想要计算 CRC 的情况,但不适用于整个缓冲区。
当然,大多数时候您可能只使用该方法的简单版本,在这种情况下参数始终为零,但通常散列和 CRC 实现是使用这样的 API 构建的,允许您根据需要分块计算 CRC。
我创建了一个简单的示例,使用一个 4 字节的小消息(在 6 字节的缓冲区中):
using System;
namespace crc16
{
class Program
{
private static ushort Crc16(byte[] bfr, int bfrlen)
{
ushort crc = 0;
for (int i = 0; i < bfrlen; i++)
{
crc ^= bfr[i];
for (int j = 0; j < 8; j++)
// assumes twos complement math
crc = (ushort)((crc >> 1)^((0 - (crc&1)) & 0xa001));
}
return crc;
}
static void Main(string[] args)
{
ushort crc;
byte[] data = new byte[6] {0x11, 0x22, 0x33, 0x44, 0x00, 0x00};
crc = Crc16(data, 4); // generate crc
data[4] = (byte)(crc & 0xff); // append crc (lsb first)
data[5] = (byte)(crc >> 8);
crc = Crc16(data, 6); // verify crc;
Console.WriteLine("{0:X4}", crc);
return;
}
}
}