2016-11-24 7 views
0

Недавно я прочитал некоторые документы и код вычисления crc (например, A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS и the implementation in Linux). Насколько я понимаю, crc выполняется байт за байт, начиная с определенного адреса.Как вычислить crc16 на структуре

пример из ядра Linux:

u16 crc16(u16 crc, u8 const *buffer, size_t len) 
{ 
    while (len--) 
    crc = crc16_byte(crc, *buffer++); 
    return crc; 
} 

Теперь я спрашиваю себя, это можно легко сделать это с struct?

+1

Вы можете применить указатель к структуре: 'struct any x; crc16 (crc, (u8 const *) & x, sizeof (struct whatever)); ' –

+1

Вы можете столкнуться с некоторыми проблемами, если полагаетесь на CRC как один и тот же кросс-компилятор (по крайней мере), (например, заполнение структуры) –

+0

@ Джонни Мопп дал ответ, но есть недостаток: «Заполнение». Структура может содержать добавку, вставленную компилятором, значение прокладки неопределенно, но будет использоваться при вычислении контрольной суммы. Рекомендуется явно установить всю структуру в ноль с помощью 'memset' до инициализации. В противном случае две иначе идентичные структуры могут создавать разные контрольные суммы. –

ответ

4

В общем, если вы хотите разумного результата, нет.

Это связано с тем, что CRC предполагается вычислять по последовательности «известных» байтов, а структура в памяти - , а не - последовательность известных байтов. Для выравнивания могут быть байты заполнения, о которых вы не всегда знаете или имеете контроль, и, конечно, различные поля могут иметь различные размеры (как и сам struct) на разных системах/платформах.

Если вы сначала можете сериализовать структуру в последовательность байтов с известным и стабильным отображением, тогда, конечно, вы можете применить CRC к этой последовательности. Это (тонко) намечено аргументом buffer, равным const u8 *, то есть указателем на постоянный байт, а не const void *.

Если вы не заботитесь, а не против разрыва, если (например) изменить настройки компилятора и/или переместить программу в другую систему, вы могли бы просто использовать:

const struct mystruct s = { ... }; 
const u16 crc = crc16(0, (u8 *) &s, sizeof s); 

Но этот будет содержать любые дополнения в структуре, поэтому это очень опасно.

+0

упаковка структуры может немного помочь в этой ситуации – j123b567

+0

@ j123b567: Упаковка не является стандартной и ничего не гарантирует. Мало того, что его можно игнорировать, но он также не определяет endianess, бит-поля и т. Д. Также на многих архитектурах упаковка будет либо замедлять доступ, либо даже требовать ручной сборки типов с 'sizeof> 1'. – Olaf

+0

@Olaf Вы, конечно, правы. Но вы всегда пишете код, который нужно компилировать каждым компилятором и запускать на любом процессоре? Если вы знакомы с окружающей средой, упаковка структур может быть полезна, и это может быть легкой трюк, чтобы справиться с этой ситуацией. (например, запись структуры конфигурации с помощью CRC в EEPROM на микроконтроллере) – j123b567