Цитата(Jenya7 @ Jan 21 2015, 00:05)

а struct как определить? typedef struct {unsigned char paket[BUF_SIZE]} message_t; ?
Да как вам надо, так и определите.
Суть в том, что если функция подсчёта crc принимает в качестве аргумента указатель на void, то при передаче любого другого указателя в эту функцию к нему не надо применять приведение типа.
Поясню. Пусть у нас есть две функции подсчёта crc:
Код
uint32_t crc1(const void * buf, size_t size);
uint32_t crc2(const uint8_t * buf, size_t size);
И пусть мы хотим посчитать crc следующих объектов:
Код
int intArray[10];
uint8_t byteBuf[20];
struct config_t
{
uint32_t serial;
uint32_t baudrate;
}config;
Так вот. Используя первую функцию, мы можем написать:
Код
crc1(intArray, 10*sizeof(int));
crc1(byteBuf, 20);
crc1(&config, sizeof(config));
Для второй функции нам в двух случаях придётся делать приведение типа:
Код
crc2((const uint8_t *)intArray, 10*sizeof(int));
crc2((const uint8_t *)&config, sizeof(config));
Что касаемо добавления const к неизменяемым параметрам. Это очень полезное правило.
Во-первых, это помогает компилятору в плане оптимизации. (Он имеет право не перечитывать такие объекты после вызова функции)
И, во-вторых, это помогает использующему эту функцию программисту быстрее понять логику работы функции. (И не надо думать об этом программисте, как о каком-то абстрактном человеке (и пусть это будет "его ответственность"). В подавляющем большинстве случаев этим программистом будете вы

)
Пример: void * memcpy (void * destination, const void * source, size_t num);
(Если вы случайно перепутаете параметры, то есть шанс, что компилятор вас поправит).
Если бы я знал, что такое электричество...