Menu
Coddy logo textTech

Deep Copy

Part of the Object Oriented Programming section of Coddy's C journey — lesson 15 of 61.

When you assign one struct to another in C, you get a shallow copy—all fields are copied byte-for-byte. This works fine for simple values like integers, but creates a problem with pointers: both structs end up pointing to the same memory.

typedef struct {
    char *name;
    int age;
} Person;

Person alice = {"Alice", 30};
Person copy = alice;  // Shallow copy!
// Both alice.name and copy.name point to the SAME string

If you free one, the other becomes invalid. If you modify the string through one, both see the change. This is rarely what you want.

A deep copy allocates new memory for pointer members and copies the actual data:

Person *clone_person(const Person *original) {
    Person *copy = malloc(sizeof(Person));
    copy->name = malloc(strlen(original->name) + 1);
    strcpy(copy->name, original->name);
    copy->age = original->age;
    return copy;
}

Now each object owns its own string. You can modify or free one without affecting the other. The pattern is straightforward: for each pointer member, allocate fresh memory and copy the contents—not just the address.

challenge icon

Challenge

Easy

Let's build a Student module that demonstrates the deep copy pattern. You'll create a cloning function that produces a completely independent copy of a student object—one where modifying or freeing the original has no effect on the clone.

You'll create three files:

  • student.h: Declare a Student struct with two members: char *name (a dynamically allocated string) and int grade. Declare three functions:
    • create_student — constructor that takes a name and grade, returns a pointer to a new Student
    • clone_student — takes a const Student * and returns a pointer to a new, independent copy
    • free_student — destructor that properly frees all allocated memory
    Use include guards with the symbol STUDENT_H.
  • student.c: Implement all three functions. Your clone_student function is the key—it must allocate fresh memory for both the struct and the name string, then copy the actual string data (not just the pointer address). This ensures the clone owns its own memory completely separate from the original.
  • main.c: Create a student, clone it, display both students' information, then properly clean up both objects.

You will receive two inputs: the student name (a string) and the grade (an integer).

In your main file, create a student with the provided values, then create a clone of that student. Print both the original and the clone's information to verify they contain the same data. Finally, free both students and print a confirmation.

Print the output in this format:

Original: {name}, Grade: {grade}
Clone: {name}, Grade: {grade}
Both freed

For example, with inputs Alice and 95, the output would be:

Original: Alice, Grade: 95
Clone: Alice, Grade: 95
Both freed

The deep copy pattern ensures that each object is truly independent—the clone has its own allocated string, not a shared pointer to the original's memory.

Cheat sheet

When you assign one struct to another in C, you get a shallow copy—all fields are copied byte-for-byte. With pointers, both structs end up pointing to the same memory:

typedef struct {
    char *name;
    int age;
} Person;

Person alice = {"Alice", 30};
Person copy = alice;  // Shallow copy!
// Both alice.name and copy.name point to the SAME string

A deep copy allocates new memory for pointer members and copies the actual data:

Person *clone_person(const Person *original) {
    Person *copy = malloc(sizeof(Person));
    copy->name = malloc(strlen(original->name) + 1);
    strcpy(copy->name, original->name);
    copy->age = original->age;
    return copy;
}

The deep copy pattern: for each pointer member, allocate fresh memory and copy the contents—not just the address. This ensures each object owns its own memory and can be modified or freed independently.

Try it yourself

#include <stdio.h>
#include <stdlib.h>
#include "student.h"

int main() {
    char name[100];
    int grade;
    
    // Read input
    scanf("%s", name);
    scanf("%d", &grade);
    
    // TODO: Create a student with the provided name and grade
    
    // TODO: Create a clone of the student
    
    // TODO: Print the original student's information
    // Format: "Original: {name}, Grade: {grade}"
    
    // TODO: Print the clone's information
    // Format: "Clone: {name}, Grade: {grade}"
    
    // TODO: Free both students
    
    // Print confirmation
    printf("Both freed\n");
    
    return 0;
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming