Thread: Copy a whole structure in one of its member in C

  1. #1
    Registered User
    Join Date
    Nov 2016
    Posts
    4

    Copy a whole structure in one of its member in C

    Hi,

    I am not having very good C knowledge. I am learning this language.
    I want to copy all structure data into one of its char array member. I tried memcpy, memmove but it's not working. Any help is appreciated.

    Sample code:

    Code:
    struct send_buf {
        struct service_t *service_info;
        bool last_pkt;
        size_t remaining;
        size_t pkt_len;
        char payload[0];
    };  
    
     
    struct send_buf *msg= (struct send_buf *)malloc(sizeof(struct send_buf)) + 1024];
    
    msg->last_pkt = false;
    msg->service_info->tag = 2;
    msg->remaining = 4090;
    msg->pkt_len = 1080;
    // Trying to copy this data to payload member
    
    memcpy(msg->payload, &msg, sizeof(struct send_buf));
    
    /* Trying to print data but got nothing. 
     * Once these header data gets copied, I want to copy 
     *actual payload to this char pointer using strcat.
     */
    Any suggestions or help is much appreciated. Thank you in advance !

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > memcpy(msg->payload, &msg, sizeof(struct send_buf));
    Well &msg is the address of the pointer itself, not the data it points to.

    Setting aside the issue of why you would want to make two copies of the same data inside itself, then this works
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    struct send_buf {
        size_t remaining;
        size_t pkt_len;
        char payload[0];
    };  
    
    int main ( ) {
      struct send_buf *msg= (struct send_buf *)malloc(sizeof(struct send_buf) + 1024);
      msg->remaining = 4090;
      msg->pkt_len = 1080;
    
      // Trying to copy this data to payload member
      //!! note: no & on msg
      memcpy(msg->payload, msg, sizeof(struct send_buf));
      return 0;
    }
    
    
    $ gcc -g main.c
    $ gdb -q ./a.out
    Reading symbols from ./a.out...done.
    (gdb) b 18
    Breakpoint 1 at 0x40056d: file main.c, line 18.
    (gdb) run
    Starting program: /home/sc/Documents/a.out 
    
    Breakpoint 1, main () at main.c:18
    18	  return 0;
    (gdb) x/50xb msg
    0x602010:	0xfa	0x0f	0x00	0x00	0x00	0x00	0x00	0x00
    0x602018:	0x38	0x04	0x00	0x00	0x00	0x00	0x00	0x00
    0x602020:	0xfa	0x0f	0x00	0x00	0x00	0x00	0x00	0x00
    0x602028:	0x38	0x04	0x00	0x00	0x00	0x00	0x00	0x00
    0x602030:	0x00	0x00	0x00	0x00	0x00	0x00	0x00	0x00
    0x602038:	0x00	0x00	0x00	0x00	0x00	0x00	0x00	0x00
    0x602040:	0x00	0x00
    (gdb) p/x *msg
    $1 = {remaining = 0xffa, pkt_len = 0x438, payload = 0x602020}
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Nov 2016
    Posts
    4
    Quote Originally Posted by Salem View Post
    > memcpy(msg->payload, &msg, sizeof(struct send_buf));
    Well &msg is the address of the pointer itself, not the data it points to.

    Setting aside the issue of why you would want to make two copies of the same data inside itself, then this works
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    struct send_buf {
        size_t remaining;
        size_t pkt_len;
        char payload[0];
    };  
    
    int main ( ) {
      struct send_buf *msg= (struct send_buf *)malloc(sizeof(struct send_buf) + 1024);
      msg->remaining = 4090;
      msg->pkt_len = 1080;
    
      // Trying to copy this data to payload member
      //!! note: no & on msg
      memcpy(msg->payload, msg, sizeof(struct send_buf));
      return 0;
    }
    
    
    $ gcc -g main.c
    $ gdb -q ./a.out
    Reading symbols from ./a.out...done.
    (gdb) b 18
    Breakpoint 1 at 0x40056d: file main.c, line 18.
    (gdb) run
    Starting program: /home/sc/Documents/a.out 
    
    Breakpoint 1, main () at main.c:18
    18      return 0;
    (gdb) x/50xb msg
    0x602010:    0xfa    0x0f    0x00    0x00    0x00    0x00    0x00    0x00
    0x602018:    0x38    0x04    0x00    0x00    0x00    0x00    0x00    0x00
    0x602020:    0xfa    0x0f    0x00    0x00    0x00    0x00    0x00    0x00
    0x602028:    0x38    0x04    0x00    0x00    0x00    0x00    0x00    0x00
    0x602030:    0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
    0x602038:    0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
    0x602040:    0x00    0x00
    (gdb) p/x *msg
    $1 = {remaining = 0xffa, pkt_len = 0x438, payload = 0x602020}

    Thanks Salem. Appreciate your time. My final goal is to send data in chunks. Actual data is stored in structservice_t *service. I need to attach some more header and break this data into chunks before sending them to other end. The another problem is, API only accepts structservice_t *service. I got this struct from upper layer. It has following members:

    Code:
    struct service_t {
       int len;
       int *data;
    };
    This data member has all data. I need to fragment it and send it into some chunks with some header. I don't how to copy this int * to msg->payload. I tried memcpy but it gave me segmentation fault.

    Since API only accepts this, I need to define/include this structure into structsend_buf and store this chinked data back to data member of service_t structure. Do you think this approach is Okay? For example,

    Code:
    struct service_t {
       int len;               // total len
       int *data;            // It has actual data 
    };
    
    
    struct send_buf {
      struct service_t *service_info;
      bool last_pkt;
      size_t remaining;
      size_t pkt_len;
      char payload[0];
    };
    
    int send_to_m2(struct service_t *info)
    {
     
    
       struct send_buf *msg= (struct send_buf*)malloc(sizeof(struct send_buf)) + 1000];
     
       int ch_len, send_position = 0;
       msg->remaining = info->len;
    
    
    do {
             ch_len = (msg->remaining > 1024) ? 1024 : msg->remaining;
      
             if(msg->remaining > 1024) {
                 msg->last_pkt = false;
             } else {
                 msg->last_pkt = true;
             }   
              memcpy(msg->payload, msg, sizeof(structsend_buf));     
    
             // OR  copy everything to msg->service_info->data and then use strncat to copy data -----?????
              printf("Data = %s\n", msg);
    
              // Now copy only first chunk length data to "data" member of struct service_t
    
    
              strncat((char *)msg->service_info->data, (char *)info->data + send_position, ch_len );
             //  GETTING ERROR
    
    
              msg->pkt_len = ch_len + sizeof(struct send_buf);
              service_info->len = msg->pkt_len;
    
    
              send_data(&info_send);       // GIVEN API
    
    
              msg->remaining -= ch_len;
              send_position += ch_len;
    
       }while(msg->last_pkt != true);
            
            return 0;
    }
    
    




    I hope I make sense. I know I didn't explain the problem nicely. I appreciate if you can help me.

    Last edited by mehtame026; 11-11-2016 at 01:15 PM. Reason: Added few comments

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > struct send_buf *msg= (struct send_buf*)malloc(sizeof(struct send_buf)) + 1000];
    Posting something which compiles would help.

    If you're sending 1024 byte chunks, then you need to add 1024 to the size of send_buf

    > struct service_t *service_info;
    Why do you need this in send_buf?
    It seems entirely pointless to do anything else if it's as simple as just passing on service_info.

    Perhaps something like this
    Code:
    #define BLOCK_SIZE 1024
    
    struct service_t {
       int len;               // total len
       int *data;            // It has actual data 
    };
    
    struct send_buf {
      struct service_t *service_info;  //!! why is this here?
      bool last_pkt;
      size_t remaining;
      size_t pkt_len;
      char payload[0];
    };
    
    int send_to_m2(struct service_t *info)
    {
      struct send_buf *msg= malloc(sizeof(struct send_buf) + BLOCK_SIZE);  // if you need a cast, you're doing something wrong
      int ch_len = 0;
      char *cdata = (char*)info->data;
    
      msg->remaining = info->len;
    
      do {
        ch_len = (msg->remaining > BLOCK_SIZE) ? BLOCK_SIZE : msg->remaining;
    
        if(msg->remaining > BLOCK_SIZE) {
          msg->last_pkt = false;
        } else {
          msg->last_pkt = true;
        }   
        msg->pkt_len = ch_len + sizeof(struct send_buf);
        memcpy(msg->payload, cdata, msg->pkt_len);     
    
        // why are you overwriting your input structure?
        // service_info->len = msg->pkt_len;
    
        send_data(msg);       // GIVEN API
    
        msg->remaining -= ch_len;
        cdata += ch_len;
    
      }while(msg->last_pkt != true);
            
      free(msg);
      return 0;
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Nov 2016
    Posts
    4
    Quote Originally Posted by Salem View Post
    > struct send_buf *msg= (struct send_buf*)malloc(sizeof(struct send_buf)) + 1000];
    Posting something which compiles would help.

    If you're sending 1024 byte chunks, then you need to add 1024 to the size of send_buf

    > struct service_t *service_info;
    Why do you need this in send_buf?
    It seems entirely pointless to do anything else if it's as simple as just passing on service_info.

    Perhaps something like this
    Code:
    #define BLOCK_SIZE 1024
    
    struct service_t {
       int len;               // total len
       int *data;            // It has actual data 
    };
    
    struct send_buf {
      struct service_t *service_info;  //!! why is this here?
      bool last_pkt;
      size_t remaining;
      size_t pkt_len;
      char payload[0];
    };
    
    int send_to_m2(struct service_t *info)
    {
      struct send_buf *msg= malloc(sizeof(struct send_buf) + BLOCK_SIZE);  // if you need a cast, you're doing something wrong
      int ch_len = 0;
      char *cdata = (char*)info->data;
    
      msg->remaining = info->len;
    
      do {
        ch_len = (msg->remaining > BLOCK_SIZE) ? BLOCK_SIZE : msg->remaining;
    
        if(msg->remaining > BLOCK_SIZE) {
          msg->last_pkt = false;
        } else {
          msg->last_pkt = true;
        }   
        msg->pkt_len = ch_len + sizeof(struct send_buf);
        memcpy(msg->payload, cdata, msg->pkt_len);     
    
        // why are you overwriting your input structure?
        // service_info->len = msg->pkt_len;
    
        send_data(msg);       // GIVEN API
    
        msg->remaining -= ch_len;
        cdata += ch_len;
    
      }while(msg->last_pkt != true);
            
      free(msg);
      return 0;
    }

    Thanks Salem! My API only uses struct service_t to send data to other end. So I need to append header (or struct send_buf data) to service_info->data. And send 1024 bytes payload. "send_data(msg)" I can't do this. I have to pass struct service_t as an argument. Appreciate your efforts and time.

  6. #6
    Registered User
    Join Date
    Nov 2016
    Posts
    4
    @Salem: Any suggestions how to do this? Can you please tell me how can I copy structure to int *? I want to copy this send_buf structure to service_t->data.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    I'm confused, you wanted to copy packets of service_t into send_buf, and now you want to copy the whole lot back into service_t ?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 10
    Last Post: 03-18-2014, 10:43 AM
  2. structure copy
    By vjefcoat in forum C Programming
    Replies: 7
    Last Post: 12-01-2010, 07:14 AM
  3. Replies: 51
    Last Post: 02-09-2009, 05:35 PM
  4. member of a structure that is a stucture member
    By MK27 in forum C Programming
    Replies: 2
    Last Post: 11-29-2008, 10:33 AM
  5. Member-Wise Copy Misunderstanding
    By Stealth0 in forum C++ Programming
    Replies: 1
    Last Post: 10-21-2002, 07:17 PM

Tags for this Thread