Newbie: How to Copy a Struct into an Array

Discussion in 'C Programming' started by R Cubed, May 29, 2004.

  1. R Cubed

    R Cubed Guest

    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
     
    R Cubed, May 29, 2004
    #1
    1. Advertising

  2. R Cubed

    Ben Pfaff Guest

    (R Cubed) writes:

    > 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.
    --
    int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.\
    \n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
    );while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p\
    );}return 0;}
     
    Ben Pfaff, May 29, 2004
    #2
    1. Advertising

  3. R Cubed

    CBFalconer Guest

    R Cubed wrote:
    >
    > 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.

    --
    Chuck F () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
     
    CBFalconer, May 29, 2004
    #3
  4. R Cubed

    Ralmin Guest

    "CBFalconer" <> wrote:
    > R Cubed wrote:
    > > 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?

    --
    Simon.
     
    Ralmin, May 29, 2004
    #4
  5. R Cubed

    kal Guest

    (R Cubed) wrote in message news:<>...

    > 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>
     
    kal, May 31, 2004
    #5
  6. R Cubed

    Neil Kurzman Guest

    R Cubed wrote:

    > 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.
     
    Neil Kurzman, May 31, 2004
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris Fogelklou
    Replies:
    36
    Views:
    1,393
    Chris Fogelklou
    Apr 20, 2004
  2. Alex
    Replies:
    2
    Views:
    1,242
  3. Replies:
    18
    Views:
    7,106
    Karl Heinz Buchegger
    Jul 22, 2005
  4. Replies:
    26
    Views:
    2,128
    Roland Pibinger
    Sep 1, 2006
  5. Tuan  Bui
    Replies:
    14
    Views:
    479
    it_says_BALLS_on_your forehead
    Jul 29, 2005
Loading...

Share This Page