32-битный расчет CRC не соответствует онлайн-генератору

Может ли кто-нибудь помочь мне в этом вычислении 32-битного CRC.

Это фрагмент кода, который я использовал для вычисления 32-битного CRC.

static unsigned int crc32_table[256];

void make_crc_table()
{
   int j;
   unsigned int crc,byte, mask;

   /* Set up the table, if necessary. */
   if (crc32_table[1] == 0)
   {
      for (byte = 0; byte <= 255; byte++)
      {
         crc = byte;
         for (j = 7; j >= 0; j--)   // Do eight times
         {
            mask = -(crc & 1);
            crc = (crc >> 1) ^ (0xEDB88320 & mask);
         }
         crc32_table[byte] = crc;
      }
   }

   for (j=0;j<10;j++)
      printf("crc32_table[%d] = %x\n",j,crc32_table[j]);
}

unsigned int crc32cx(unsigned int crc,unsigned char *message,int len)
{
   unsigned int word;

   do
   {
     if((word = *(unsigned int *)message) & 0xFF)
     {
       crc = crc ^ word;
       crc = (crc >> 8) ^ crc32_table[crc & 0xFF];
       crc = (crc >> 8) ^ crc32_table[crc & 0xFF];
       crc = (crc >> 8) ^ crc32_table[crc & 0xFF];
       crc = (crc >> 8) ^ crc32_table[crc & 0xFF];
       message = message + 4;
       len--;
     }
   }while(len == 0);

   return ~crc;
}

main()
{
   unsigned int crc = 0xFFFFFFFF;
   unsigned char buff[100] = ABCDEFGH;
   int len;  // lenght in bytes

   len = (((strlen(buff)%8)==0) ? (strlen(buff)/8) : ((strlen(buff)/8)+1));
   printf("lenght in bytes %d\n",len);

   make_crc_table();
   printf("crc = %x\n",crc32cx(crc,buff,len));
}

Может кто-нибудь помочь мне, почему это не соответствует онлайн-калькулятору 32-битного CRC. Ссылка приведена ниже

http://www.tahapaksu.com/crc/

При вводе buff=12345678 моя CRC сопоставляется с онлайновой. Для других значений, таких как buff = ABCD1234, вывод не совпадает.

Спасибо.


person user3654    schedule 11.02.2016    source источник
comment
Чтобы помочь другим людям помочь вам, добавьте тег языка для этого вопроса.   -  person Wai Ha Lee    schedule 11.02.2016
comment
По вашей ссылке на Lammert Bies он делает доступной библиотеку. Вы можете проверить свое решение в этой библиотеке.   -  person Paul Ogilvie    schedule 11.02.2016
comment
Вместо объявления вашего unsigned char buff[100] = ABCDEFGH;вы должны использовать кавычки, такие как unsigned char buff[100] = "ABCDEFGH";   -  person Frodo    schedule 11.02.2016
comment
@Frodo Я уверен, что проблема не в кавычках; без них код даже не скомпилируется :)   -  person Pandrei    schedule 11.02.2016
comment
Какой смысл имеет mask = -(crc & 1);? Все задействованные числа являются беззнаковыми.   -  person Lundin    schedule 11.02.2016
comment
@Pandrei Отсутствие кавычек является очень серьезной проблемой, поскольку предполагает, что это не настоящий код, а что-то другое.   -  person Lundin    schedule 11.02.2016
comment
@ user3654, не могли бы вы отредактировать текст вопроса, чтобы показать, как вы вызывали функцию CRC для двух случаев «12345678», «ABCD1234»; просто выполните оба действия в одном и том же основном вызове и добавьте код в вопрос.   -  person Pandrei    schedule 11.02.2016


Ответы (2)


Проблема здесь в том, как написан код; позволь мне объяснить:

unsigned int crc32cx(unsigned int crc,unsigned char *message,int len)
{
   unsigned int word;

   do
   {
     if((word = *(unsigned int *)message) & 0xFF)
     {
       crc = crc ^ word;
       crc = (crc >> 8) ^ crc32_table[crc & 0xFF];
       crc = (crc >> 8) ^ crc32_table[crc & 0xFF];
       crc = (crc >> 8) ^ crc32_table[crc & 0xFF];
       crc = (crc >> 8) ^ crc32_table[crc & 0xFF];
       message = message + 4;
       len--;
     }
   }while(len == 0);

   return ~crc;
}

Что делает эта функция, так это считывает 4 символа за раз и вычисляет CRC (операция XOR); Википедия объясняет математику, стоящую за этим. Но вы делаете эту операцию len раз

unsigned char buff[100] = ABCDEFGH;
int len;  // lenght in bytes
printf("crc = %x\n",crc32cx(crc,buff,4));

Итак, в вашем случае вы будете читать 4x4 байта; И ваш буфер будет содержать:

buff = ['A' 'B' 'C' 'D' 'E' 'F' 'G' 'H' '\n' 'trash' 'trash'.... ]

У вас есть 8 байтов информации, за которыми следует '\n', поскольку вы назначаете буферу строку, а не мусор, поскольку буфер размещается в стеке. И вы читаете 16 байт. Я уверен, что вы уже заметили проблему, но на всякий случай я думаю, что crc32cx(crc,buff,2) должен решить вашу проблему.

person Pandrei    schedule 11.02.2016
comment
Извините, это опечатка, что printf(crc = %x\n,crc32cx(crc,buff,4)); На самом деле я назвал crc32cx(crc,buff,len); В этом случае crc32cx(crc,buff,2) и crc32cx(crc,buff,len=1) из-за do while являются одним и тем же. - person user3654; 11.02.2016
comment
Будет ли разница в вычислении 32-битного алгоритма CRC, если входное сообщение больше 1 байта? - person user3654; 11.02.2016
comment
@user3654 user3654 да, будет разница; len — это длина в целых числах без знака, а не в байтах. Вы читаете по 4 байта за раз при вычислении CRC. если в вашем буфере только один байт, остальные будут заполнены тем, что находится в стеке; не 0 с - person Pandrei; 11.02.2016

Ваш код CRC очень нестандартен. При использовании табличного метода вы должны вводить данные байт за байтом, а не 4-байтовый фрагмент за фрагментом, что определенно вызывает некоторые проблемы с вводом и логикой. Самой большой из них является эта строка if(word = *(unsigned int *)message) & 0xFF), которая совершенно не нужна и в некоторых сценариях будет игнорировать действительные входящие данные.

Хорошая, простая и чистая реализация crc32 C может быть здесь. Посмотрев на него и на свой и сделав несколько настроек, все заработало.

В вашей функции вы бы изменили цикл и свою переменную на:

   unsigned char word;
   do
   {
       word = *message;
       crc = crc ^ word;
       crc = (crc >> 8) ^ crc32_table[crc & 0xFF];
       message++;
       len--;

   }while(len > 0);

И теперь в вашем основном вы можете найти длину ваших входных данных, просто используя len = strlen(buff).

person Dom    schedule 11.02.2016