2016-04-12 2 views
0

Я дал массив структур:Безопасный массива структуры, как обычный поток байт

typedef struct sRawMsg{ 
    int a; 
}sRawMsg; 

sRawMsg RawMsg[10]; 

Сначала запись структуры массива заполняется данными. Затем данные копируются в выходной буфер, заданный как 2D-массив.

// sending buffer which allocates memory for the array struct 
static unsigned char sendingBuffer[10][sizeof(sRawMsg)]; 

for(int i = 0; i < 10; ++i) 
{ 
    sRawMsg* pMsg = &(RawMsg[i]); 
    // data is now stored in the struct array @ pos i 
    ... 
    // data from the struct entry is now saved in the output sending buffer 
    memcopy(&(sendingBuffer[i][0]), pMsg, sizeof(sRawMsg)); 
} 

Полученный выходной буфер передается как простой массив байтов по беспроводному соединению. Поскольку я новичок в программировании на языке C, я хочу спросить, существует ли более эффективный/элегантный/безопасный способ обработки данных массива struct.

+1

Помимо ошибочного 'memcpy()', это выглядит хорошо. Вы можете оставить некоторые из круглых скобок и сократить (украсить) код. – EOF

+0

Вы ищете «сериализацию». Не просто писать внутренние структуры данных, это хороший способ неприятностей. – Olaf

ответ

2

Поскольку вы не имеете отступов в структуре (один элемент структура не имеет отступов с любым нормальным компилятором), вы могли бы просто передать

(unsigned char *)&RawMsg[0] 

в качестве аргумента для вашей отправки функции.

Если вы преобразовывали данные в фиксированный формат (например, порядок сети) или если ваша структура включала смесь типов с дополнением между элементами или если ваша структура включала указатели на строки (или другие указатели на данные) , вам придется больше работать - используйте сериализацию, аналогичную тому, что вы делаете. С указателями на строки вам, вероятно, потребуется протокол, который знает, как определить длины строк. Одно из таких соглашений известно как TLV (Type, length, value). Другой (гораздо более сложный) - ASN.1. Или вы можете использовать такой формат, как JSON или BSON, или, может быть, Protocol buffers.

+0

Не уверен, но я думаю, что в конце концов, возможно, будет дополнение в конце, например. для обеспечения конкретного выравнивания. И это меньше зависит от компилятора, чем от ABI. И стандарт очень хорошо позволяет это. – Olaf

+0

@Olaf: Идите эксперимент - вернитесь, когда найдете структуру, которая имеет один элемент, который также имеет отступы. Поля бит не учитываются. По определению массив типа T выставляется последовательно, без пробелов между ними. Если у вас есть 'struct U {T t; }; ', тогда ему нужно только одно и то же пространство и выравнивание, как тип T, поэтому массив U обычно состоит из последовательных элементов без необходимости заполнения. Компилятор _could_ add padding, но компиляторы не допускают, чтобы их компиляторы добавили ненужное дополнение. –

+0

Экспериментирование - плохой совет в C; вполне может быть сломанный компилятор. Я не сомневался, что «массив типа Т выставляется последовательно без прокладки между». Но здесь 'T' является' struct', а не тем, что содержит. Я согласен, что это может быть более теоретическим, но бесполезно полагаться на него. В общем, такая сериализация - плохая идея. Вместо этого следует использовать сериализацию по элементам в хорошо определенный формат передачи (или хранения). Не обязательно формат символа или именованные записи. – Olaf