Я читал о CRC и наткнулся на каталог CRC и эту статью о CRC-CCITT.
Я реализовал MyCrc16
(код см. ниже) на основе второй ссылки.
Который просто берет байты по порядку, биты в обратном порядке и сдвигает их один за другим в (начальный) CRC, а затем XOR с полиномом, чтобы получить остатки, плюс увеличение в конце.
Теперь... У меня также была некоторая ранее существовавшая реализация CRC16 (OtherCrc16
), которая, согласно каталогу, является CRC-16/CCITT-FALSE.
Чего я не понимаю, так это почему OtherCrc16
работает? поскольку первый байт ввода и все остальные после него подвергаются операции XOR с (начальным) CRC, а не добавляются к нему, как в другой реализации. И когда он перебирает биты, он не принимает во внимание то, что первый алгоритм считает «сдвигом ввода в CRC», вместо этого он просто XOR с полиномом, если это необходимо.
Я пропустил какое-то свойство операции XOR? На мой взгляд, два алгоритма должны иметь одинаковый результат (конечно, не учитывая увеличение первого), но это не так.
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
uint16_t MyCrc16(const unsigned char *data, int length, uint16_t poly, uint16_t crc)
{
for(int byte=0; byte<length; ++byte)
{
for(int bit=7; bit>=0; --bit)
{
bool doXor = false;
if(crc & 0x8000)
{
doXor = true;
}
crc <<= 1;
if(data[byte] & (1 << bit))
{
crc += 1;
}
if(doXor)
{
crc ^= poly;
}
}
}
//augument the crc with 0s
for(int i=0; i<16; i++)
{
bool doXor = false;
if(crc & 0x8000)
{
doXor = true;
}
crc = crc << 1;
if(doXor)
{
crc ^= poly;
}
}
return crc;
}
uint16_t OtherCrc16(const unsigned char *data, int length, uint16_t poly, uint16_t crc)
{
for(int i=0; i<length; i++)
{
crc = crc ^ (data[i] << 8);
for (int bit = 0; bit< 8; bit++)
{
bool doXor = false;
if(crc & 0x8000)
{
doXor = true;
}
crc <<=1;
if(doXor)
{
crc ^= poly;
}
}
}
return crc;
}
int main(void) {
// your code goes here
uint16_t poly = 0x1021;
unsigned char c[] = "123456789";
printf("My CRC = %04x\n", MyCrc16(c, 9, poly, 0xffff));
printf("Other CRC = %04x\n", OtherCrc16(c, 9, poly, 0xffff));
return 0;
}
PS: исполняемый код: http://ideone.com/mKuQqQ