Eric Bergman
Eric Bergman

Reputation: 1443

Porting CRC16 Code in C to C# .NET

So I have this C code that I need to port to C#:

C Code:

uint16 crc16_calc(volatile uint8* bytes, uint32 length)
{
   uint32 i; 
   uint32 j;
   uint16 crc = 0xFFFF; 
   uint16 word;

   for (i=0; i < length/2 ; i++)
   {
      word = ((uint16*)bytes)[i];

      // upper byte
      j = (uint8)((word ^ crc) >> 8);
      crc = (crc << 8) ^ crc16_table[j];

      // lower byte
      j = (uint8)((word ^ (crc >> 8)) & 0x00FF);
      crc = (crc << 8) ^ crc16_table[j];
   }
   return crc;
}

Ported C# Code:

public ushort CalculateChecksum(byte[] bytes)
{
    uint j = 0;
    ushort crc = 0xFFFF;
    ushort word;

    for (uint i = 0; i < bytes.Length / 2; i++)
    {
        word = bytes[i];

        // Upper byte
        j = (byte)((word ^ crc) >> 8);
        crc = (ushort)((crc << 8) ^ crc16_table[j]);

        // Lower byte
        j = (byte)((word ^ (crc >> 8)) & 0x00FF);
        crc = (ushort)((crc << 8) ^ crc16_table[j]);
    }

    return crc;
}

This C algorithm calculates the CRC16 of the supplied bytes using a lookup table crc16_table[j]

However the Ported C# code does not produce the same results as the C code, am I doing something wrong?

Upvotes: 0

Views: 712

Answers (1)

simonc
simonc

Reputation: 42215

word = ((uint16*)bytes)[i];

reads two bytes from bytes into a uint16, whereas

word = bytes[i];

just reads a single byte.

Assuming you're running on a little endian machine, your C# code could change to

word  = bytes[i++];
word += bytes[i] << 8;

Or, probably better, as suggested by MerickOWA

word = BitConverter.ToInt16(bytes, i++);

Note that you could avoid the odd-looking extra increment of i by changing your loop:

for (uint i = 0; i < bytes.Length; i+=2)
{
    word = BitConverter.ToInt16(bytes, i);

Upvotes: 5

Related Questions