Newbie: How to Copy a Struct into an Array

R

R Cubed

I am currently in the process of transferring my C++ knowledge to C
for a socket programming class I am taking.

I need to send a packet using the sendto() function. This packet
contains a header and data.

I have declared the following basic struct to hold the header part of
the packet:

struct packet {
int seqNum;
int type;
int dataSize;
} header;

I have a character array called buf of size MAXPKTSIZE (defined to be
10000 bytes). I need to copy the entire header struct into this array,
and then copy an array called fileContents into this array. How can I
do this?

I have tried:
memcpy(buf,&header,12);
//size is 12 because struct contains 3 ints of 4 bytes each.

To debug, I try to fprintf the value of buf, but either nothing
prints, or I get garbage (large negative integers). How can I
accomplish this?

Also, once I have copied the struct into buf, how can I append the
packet data to buf?

Your help is greatly appreciated.

Thanks,
Ryan
 
B

Ben Pfaff

I need to send a packet using the sendto() function. This packet
contains a header and data.

Okay. sendto() and networking are off-topic for this newsgroup,
but that's not really what your question is about, so I'll continue.
I have declared the following basic struct to hold the header part of
the packet:

struct packet {
int seqNum;
int type;
int dataSize;
} header;

I have a character array called buf of size MAXPKTSIZE (defined to be
10000 bytes). I need to copy the entire header struct into this array,
and then copy an array called fileContents into this array. How can I
do this?

This is probably not a good idea. If you do it this way, then
you'll have trouble getting different kinds of machines to talk,
because different machines have different sizes and formats for C
types. For example, some machines have 2-byte (16-bit) ints,
whereas others have 32-bit or 64-int ints. Some machines use
little-endian byte order, other machines use big-endian byte
order. (There are other possible differences in data formats,
but these are by far the most common.) Finally, different
machines will put different amounts of padding between and after
structure members.

You'd be better off transforming your data into a portable form.
For example, `unsigned char' is generally 8 bits (and always at
least 8 bits) so you could do something like this:

unsigned char buffer[6];
buffer[0] = (unsigned) header.seqNum >> 8;
buffer[1] = (unsigned) header.seqNum & 0xff;
buffer[2] = (unsigned) header.type >> 8;
buffer[3] = (unsigned) header.type & 0xff;
buffer[4] = (unsigned) header.dataSize >> 8;
buffer[5] = (unsigned) header.dataSize & 0xff;

as long as you knew that the header fields were in the 16-bit
range. (The casts to unsigned may not be strictly necessary, but
they make the code more obviously correct.) Then on the other
end of the connection, you could reconstitute the proper values
like so:

header.seqNum = (buffer[0] << 8) | buffer[1];
header.type = (buffer[2] << 8) | buffer[3];
header.dataSize = (buffer[4] << 8) | buffer[5];

(I think that's safe for negative values, but I could be wrong.)
I have tried:
memcpy(buf,&header,12);
//size is 12 because struct contains 3 ints of 4 bytes each.

To debug, I try to fprintf the value of buf, but either nothing
prints, or I get garbage (large negative integers). How can I
accomplish this?

If you mean you tried something like this:

fprintf (stderr, "%d\n", buf);

then it's not so surprising. When you write `buf' by itself, you
get the address of the first element in buf. Printing the
address is not a meaningful thing to do. It would make more
sense to print the values of the bytes in buf, e.g. something
like this:

for (i = 0; i < 16; i++)
fprintf (stderr, "%02x ", (unsigned) buf);
Also, once I have copied the struct into buf, how can I append the
packet data to buf?

Write the packet data to succeeding bytes of the buffer.
 
C

CBFalconer

R said:
I am currently in the process of transferring my C++ knowledge to C
for a socket programming class I am taking.

I need to send a packet using the sendto() function. This packet
contains a header and data.

I have declared the following basic struct to hold the header part of
the packet:

struct packet {
int seqNum;
int type;
int dataSize;
} header;

I have a character array called buf of size MAXPKTSIZE (defined to be
10000 bytes). I need to copy the entire header struct into this array,
and then copy an array called fileContents into this array. How can I
do this?

I have tried:
memcpy(buf,&header,12);
//size is 12 because struct contains 3 ints of 4 bytes each.

To debug, I try to fprintf the value of buf, but either nothing
prints, or I get garbage (large negative integers). How can I
accomplish this?

Also, once I have copied the struct into buf, how can I append the
packet data to buf?

You are starting from the wrong end. What is needed is the
definition of the header in the packet. It is probably in terms
of octets, not bytes. It certainly isn't in terms of ints.
 
R

Ralmin

CBFalconer said:
R said:
I need to send a packet using the sendto() function. This packet
contains a header and data.
[...]
You are starting from the wrong end. What is needed is the
definition of the header in the packet. It is probably in terms
of octets, not bytes. It certainly isn't in terms of ints.

You also need to know what format the sendto() function expects to receive.
Does it want one octet per byte (with only the least significant 8 bits
used), or does it want multiple octets packed into each byte? If the latter,
in what order does it expect them to be packed?
 
K

kal

I need to send a packet using the sendto() function. This packet
contains a header and data.

You have a long way to go but then it is the journey that is fun.
I have declared the following basic struct to hold the header part of
the packet:

struct packet {
int seqNum;
int type;
int dataSize;
} header;

I have a character array called buf of size MAXPKTSIZE (defined to be
10000 bytes). I need to copy the entire header struct into this array,
and then copy an array called fileContents into this array. How can I
do this?

This is [OT] so I will keep this brief.
10K is too big, keep it under 4K.

Assuming "int" is 32 bits.

<pseudo code>
char *p_packet;
char *p_data;
int data_len;
int seq_num;
int type;
int len;

len = data_len;
if (len < 0 ||len > MAXPKTSIZE - 12)
{ /*
error handling code here.
Or upgrade this to send multiple packets.
*/
}

*((int *)(p_packet)) = htonl(seq_num);
*((int *)(p_packet+4)) = htonl(type);
*((int *)(p_packet+8)) = htonl(len);

memcpy(p_packet+12,p_data,(size_t)len);

sendto(s,p_packet,12+len, ... );
</pseudo code>
 
N

Neil Kurzman

R said:
I am currently in the process of transferring my C++ knowledge to C
for a socket programming class I am taking.

I need to send a packet using the sendto() function. This packet
contains a header and data.

I have declared the following basic struct to hold the header part of
the packet:

struct packet {
int seqNum;
int type;
int dataSize;
} header;

I have a character array called buf of size MAXPKTSIZE (defined to be
10000 bytes). I need to copy the entire header struct into this array,
and then copy an array called fileContents into this array. How can I
do this?

I have tried:
memcpy(buf,&header,12);
//size is 12 because struct contains 3 ints of 4 bytes each.

To debug, I try to fprintf the value of buf, but either nothing
prints, or I get garbage (large negative integers). How can I
accomplish this?

Also, once I have copied the struct into buf, how can I append the
packet data to buf?

Your help is greatly appreciated.

Thanks,
Ryan

Specify what you want:
16 bit ints "short int"
32 bits " long int"

assuming may get you into trouble.

memcpy(buf,&header,sizeof(header)); you could also do sizeof(packet)

you may want to verify the size is 12 as an error check. You may have to
specify structure packing to get different systems to align structs the
same way.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top