You could define a structure that has a minimal array and allocate memory for a structure with a bigger array.
The following code example is not valid C, it is incomplete. It also doesn't handle possible byte order or size differences of the int
values when sent over the network to a different machine.
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);
The compiler doesn't care that you access an array index bigger than what you defined in the structure declaration. You have to check the index in your code to avoid memory access errors.
The receiver can use recvfrom()
with MSG_PEEK
and the size of the header (offsetof(struct foo, arr)
) into a temporary structure struct foo tmp;
first, next allocate memory according to the size
field, then read the full size of the structure into the dynamically allocated memory. See also How to read UDP packet with variable length in C
Or use a fixed buffer of the maximum size for recvfrom()
, then copy the data to a dynamically allocated structure. The return value of recvfrom()
will tell you the necessary size.
Edit according to suggestions in Matthias Simon's answer:
If your compiler supports zero-sized arrays the code can be simplified a bit.
In the structure definition you can use char arr[0];
instead of char arr[1];
. This allows to use sizeof struct foo
instead of offsetof(struct foo, arr)
in malloc()
, sendto()
and in recvfrom()
with MSG_PEEK
.