Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Behavior of struct copying in C

Tags:

c

struct

I have been reading a number of questions on this site about how to duplicate structs in C. I've been playing around with some code, trying to understand the differences between 'shallow' copying (where the new struct is simply assigned a pointer to the memory address of the first struct) and 'deep' copying (where the data is copied member-by-member into a new chunk of memory).

I created the following code, assuming that it would show the 'shallow' copying behavior:

#include <stdio.h>

struct tester
{
    int blob;
    int glob;
    char* doob[10];
};

int main (void)
{
    //initializing first structure
    struct tester yoob;
    yoob.blob = 1;
    yoob.glob = 2;
    *yoob.doob = "wenises";

    //initializing second structure without filling members
    struct tester newyoob;
    newyoob = yoob; 
    //assumed this line would simply copy the address pointed to      by 'yoob'

    //printing values to show that they are the same initially
    printf("Before modifying:\n");
    printf("yoob blob: %i\n", yoob.blob);
    printf("newyoob blob: %i\n", newyoob.blob);

    //modifying 'blob' in second structure. Assumed this would be mirrored by first struct
    newyoob.blob = 3;

    //printing new int values
    printf("\nAfter modifying:\n");
    printf("yoob blob: %i\n", yoob.blob);
    printf("newyoob blob: %i\n", newyoob.blob);

    //printing memory addresses
    printf("\nStruct memory addresses:\n");
    printf("yoob address: %p\n", &yoob);
    printf("newyoob address: %p\n", &newyoob);

}

Output on running:

Before modifying:
yoob blob: 1
newyoob blob: 1

After modifying:
yoob blob: 1
newyoob blob: 3

Struct memory addresses:
yoob address: 0x7fff3cd98d08
newyoob address: 0x7fff3cd98cb0

Is this code create a deep copy, as it appears, or am I misunderstanding what's happening here?

like image 659
ChippyZ Avatar asked Jan 06 '23 10:01

ChippyZ


2 Answers

The shallow vs. deep copy problem is only relevant to pointers. Given a type struct foo:

struct foo a = /* initialize */;
struct foo b = a;

All the values in a are copied to b. They are not the same variable.

However, with pointers:

struct foo *p = calloc(1, sizeof *p);
struct foo *q = p;

q now points to the same memory as p; no copying has taken place (and you run the risk of a dangling pointer once one gets freed). This is a pointer alias. In order to do a shallow copy, one would do:

struct foo *p = calloc(1, sizeof *p);
/* assign to p's fields... */

struct foo *q = calloc(1, sizeof *q);
*q = *p;

Now q has the same field values as p but points to a different block of memory.

A deep copy requires additional effort; any pointers in the structure must be traversed and have their contents copied as well. See this post for a good explanation.

like image 142
Cormac O'Brien Avatar answered Jan 09 '23 00:01

Cormac O'Brien


When you use newyoob = yoob; the compiler create code to copy the structure for you.

An important note about the copying: It's a shallow. That means if you have e.g. a structure containing pointers, it's only the actual pointers that will be copied and not what they point to, so after the copy you will have two pointers pointing to the same memory.

like image 45
Alaoui M. Avatar answered Jan 08 '23 23:01

Alaoui M.