Deep copying structs with char arrays in C (How to copy the arrays?)

Post-K&R (i.e. in standard C) you can just assign them. The function below is just to make the example clear, you would always just assign in-place:

void deepCopyPerson(struct person *target, struct person *src)
{
    *target = *src;
}

To elaborate: The char arrays are part of your struct object (true arrays, not only pointers!), and as such are allocated and copied with the object.

In order to satisfy the disbeliefers ;-) I dug around in the standard draft 1570 :

6.5.16 Assignment operators

Semantics

An assignment operator stores a value in the object designated by the left operand. [Followed by type conversion and sequencing considerations which are not relevant here.]

[...]

6.5.16.1 Simple assignment

Constraints

One of the following shall hold:

  • [...]

  • the left operand has an atomic, qualified, or unqualified version of a structure or union type compatible with the type of the right;

[...]

Semantics

In simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.


To perform a deep copy of a struct that contains arrays (without any pointers), a deep copy is simple

struct person x = {"Key", "Color", 42};   /*  initialise to something */
struct person y = x;

This doesn't work if the "strings" are pointers though. It is necessary then to allocate new strings, and then use a function like strcpy() to copy members.

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

struct pointer_person
{
    char *key;
    char *color;
    int age;
};

struct pointer_person deep_copy(struct pointer_person p)
{
     struct pointer_person retval;
     retval.key = malloc(strlen(p.key) + 1);
     strcpy(retval.key, p.key);
     retval.color = malloc(strlen(p.color) + 1);
     strcpy(retval.color, p.color);
     retval.age = p->age;
     return retval;
}

int main()
{
   struct pointer_person p;
   struct pointer_person pc;

   p.key = malloc(50);
   strcpy(p.key, "A key");
   p.color = malloc(20);
   strcpy(p.color, "A colour");
   p.key = 42;

   pc = deep_copy(p);

   /* do stuff with pc and c */

   free(p.key);
   free(p.color);
   free(pc.key);
   free(pc.color);
   return 0;
}

Some error checking left out of the above (e.g. need to check that malloc() succeeds before copying).