4

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?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
ChippyZ
  • 43
  • 2
  • `yoob` and `newyoob` are not pointers, so why do you expect they hold an address? – too honest for this site Mar 22 '16 at 17:26
  • Also, I don't think strings in C work how you think they work. – Tommy Mar 22 '16 at 20:15
  • You may, (or may not), be confused with `char* doob[10];`. `doob` is an ***array of pointers to type char*** (`10` of them) *not* an *array of char* and *not* a *pointer to array [10] of type char*. When you then do `*yoob.doob = "wenises";` you assign the address of the *string literal* `"wenises"` to the first pointer in `doob` (equivalent to `*(yoob.doob + 0)` which is just `yoob.doob[0]`). You may intend this -- it is *unclear*. It looks more like you intended either `char doob[10]` (an *array of 10 char*, requiring a `strcpy`) or `char *doob` (a single pointer). Please confirm. – David C. Rankin Aug 30 '16 at 06:01

4 Answers4

5

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.

Mac O'Brien
  • 2,407
  • 18
  • 22
3

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.

Alaoui M.
  • 41
  • 4
1

Your concept of "shallow copy" is wrong. The code

newyoob = yoob; 

is in fact creating a shallow copy of yoob to newyoob. Your variables yoob and newyoob are separate memory allocations.

Now if you did this

struct tester* newyoob = &yoob;

Then newyoob and yoob are "the same" - but again, two variables referencing the same memory region is not considered a copy.

Community
  • 1
  • 1
RamblinRose
  • 4,883
  • 2
  • 21
  • 33
0

Suppose this

typedef struct tester {
    int someInt;
    char* someString;
} tester;

Shallow copying

Then you assign one instance to another:

tester a = {1, "hohohahah"};
tester b = a;

The members of a will be copied by value, including the pointer. This means:

a.someString == b.someString // True: comparing addresses and addresses are the same.

b is a shallow copy of a because the pointed members point to the same memory.

Deep copying

A deep copy means that the pointed members are also duplicated. It would go along these lines:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct tester {
    int someInt;
    char* someString;
} tester;

void deepcopy_tester(tester *in, tester *out) {
    out->someInt = in->someInt;
    out->someString = malloc(strlen(in->someString)+1);
    strcpy(out->someString, in->someString);
}

int main() {
    tester t1 = {1, "Yo"};
    tester t2 = {0, NULL};
    deepcopy_tester(&t1, &t2);

    printf("%s\na", t2.someString);
}

This code should work, just tested with gcc.

daragua
  • 1,133
  • 6
  • 8