Вы можете определить структуру с минимальным массивом и выделить память для структуры с большим массивом.
Следующий пример кода не является допустимым C, он неполный.Он также не обрабатывает возможные различия в байтовом порядке или размерах значений int
при отправке по сети на другой компьютер.
struct foo
{
unsigned int ID;
unsigned int Num;
unsigned int size;
char arr[1];
};
int size = 123;
int i;
int ret;
struct foo *ptr = malloc(offsetof(struct foo, arr) + size);
ptr->ID = 42;
ptr->Num = 99;
ptr->size = size;
for(i=0; i<ptr->size; i++)
{
ptr->arr[i] = data;
}
ret = sendto(sockfd, ptr, offsetof(struct foo, arr) + size, flags,
dest_addr, addrlen);
Компилятору все равно, что вы получаете доступ к индексу массива большечем то, что вы определили в объявлении структуры.Вы должны проверить индекс в своем коде, чтобы избежать ошибок доступа к памяти.
Получатель может использовать recvfrom()
с MSG_PEEK
и размер заголовка (offsetof(struct foo, arr)
) во временной структуре struct foo tmp;
сначала выделите память в соответствии с полем size
, затем прочитайте полный размер структуры в динамически выделенную память.См. Также Как прочитать пакет UDP с переменной длиной в C
Или использовать фиксированный буфер максимального размера для recvfrom()
, а затем скопировать данные в динамически распределенную структуру.Возвращаемое значение recvfrom()
сообщит вам необходимый размер.
Редактируйте в соответствии с предложениями в ответе Матиаса Саймона:
Если ваш компилятор поддерживает массивы нулевого размера,код можно немного упростить.
В определении структуры вы можете использовать char arr[0];
вместо char arr[1];
.Это позволяет использовать sizeof struct foo
вместо offsetof(struct foo, arr)
в malloc()
, sendto()
и в recvfrom()
с MSG_PEEK
.